Index: /tags/uniphot-1-2/Ohana/src/uniphot/Makefile
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/Makefile	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/Makefile	(revision 5424)
@@ -0,0 +1,73 @@
+include ../../Configure
+HOME    =       $(ROOT)/src/uniphot
+CONFIG  =	$(ROOT)/config
+PROGRAM =       uniphot
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC)
+LIBS	= 	-L$(LLIB) -ldvo -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS) -Wall
+CCFLAGS	=	$(INCS) $(LIBS) -Wall
+
+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)/wcatalog.$(ARCH).o		 \
+$(SRC)/wimages.$(ARCH).o		 \
+$(SRC)/gcatalog.$(ARCH).o		 \
+$(SRC)/check_permissions.$(ARCH).o		 \
+$(SRC)/image-db.$(ARCH).o		 \
+$(SRC)/SetSignals.$(ARCH).o		 \
+$(SRC)/Shutdown.$(ARCH).o		 \
+$(SRC)/misc.$(ARCH).o
+
+OBJ = $(UNIPHOT)
+
+default: $(PROGRAM)
+
+$(UNIPHOT): $(INC)/uniphot.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
Index: /tags/uniphot-1-2/Ohana/src/uniphot/bin/.cvsignore
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/bin/.cvsignore	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/bin/.cvsignore	(revision 5424)
@@ -0,0 +1,1 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
Index: /tags/uniphot-1-2/Ohana/src/uniphot/doc/ChangeLog.txt
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/doc/ChangeLog.txt	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/doc/ChangeLog.txt	(revision 5424)
@@ -0,0 +1,14 @@
+
+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: /tags/uniphot-1-2/Ohana/src/uniphot/doc/notes.txt
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/doc/notes.txt	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/doc/notes.txt	(revision 5424)
@@ -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: /tags/uniphot-1-2/Ohana/src/uniphot/include/uniphot.h
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/include/uniphot.h	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/include/uniphot.h	(revision 5424)
@@ -0,0 +1,105 @@
+# 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);
Index: /tags/uniphot-1-2/Ohana/src/uniphot/src/ConfigInit.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/ConfigInit.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/ConfigInit.c	(revision 5424)
@@ -0,0 +1,39 @@
+# include "uniphot.h"
+
+void ConfigInit (int *argc, char **argv) {
+
+  double ZERO_POINT;
+  char  *config, *file;
+  char   PhotCodeFile[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, "IMAGE_CATALOG",          "%s",  0, ImageCat);
+  ScanConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
+  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");
+
+  if (!LoadPhotcodes (PhotCodeFile)) {
+    fprintf (stderr, "error loading photcodes\n");
+    exit (0);
+  }
+
+}
Index: /tags/uniphot-1-2/Ohana/src/uniphot/src/SetSignals.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/SetSignals.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/SetSignals.c	(revision 5424)
@@ -0,0 +1,118 @@
+# 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 SIGPWR:     /* power failure - why ignore this? */
+    case SIGWINCH:   /* window resized */
+    case SIGCONT:    /* continue - maintain this action */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? */
+    case SIGURG:     /* socket signal, ignore this */
+      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: /tags/uniphot-1-2/Ohana/src/uniphot/src/Shutdown.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/Shutdown.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/Shutdown.c	(revision 5424)
@@ -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);
+  fits_db_close (db);
+  fprintf (stderr, "ERROR: addstar halted\n");
+  exit (1);
+}
+
Index: /tags/uniphot-1-2/Ohana/src/uniphot/src/args.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/args.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/args.c	(revision 5424)
@@ -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 (!str_to_time (argv[N], &TSTART)) { 
+      fprintf (stderr, "ERROR: syntax error\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    if (!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: /tags/uniphot-1-2/Ohana/src/uniphot/src/check_permissions.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/check_permissions.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/check_permissions.c	(revision 5424)
@@ -0,0 +1,67 @@
+# include "uniphot.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: /tags/uniphot-1-2/Ohana/src/uniphot/src/dumpresult.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/dumpresult.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/dumpresult.c	(revision 5424)
@@ -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: /tags/uniphot-1-2/Ohana/src/uniphot/src/find_image_sgroups.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/find_image_sgroups.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/find_image_sgroups.c	(revision 5424)
@@ -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 = fits_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: /tags/uniphot-1-2/Ohana/src/uniphot/src/find_image_tgroups.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/find_image_tgroups.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/find_image_tgroups.c	(revision 5424)
@@ -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 = fits_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, 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 = sec_to_date (tmin[i]);
+    stop = 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: /tags/uniphot-1-2/Ohana/src/uniphot/src/fit_groups.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/fit_groups.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/fit_groups.c	(revision 5424)
@@ -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_PS;
+      Mgrp = sgroup[0].M;
+      mlist[Nlist] = (Mcal - Mgrp);
+      dlist[Nlist] = tgroup[i].image[j][0].dMcal_PS;
+      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_PS;
+      Mgrp = tgroup[0].M;
+      mlist[Nlist] = (Mcal - Mgrp);
+      dlist[Nlist] = sgroup[i].image[j][0].dMcal_PS;
+      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: /tags/uniphot-1-2/Ohana/src/uniphot/src/gcatalog.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/gcatalog.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/gcatalog.c	(revision 5424)
@@ -0,0 +1,31 @@
+# include "uniphot.h"
+
+int gcatalog (Catalog *catalog) {
+
+  catalog[0].catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+  /* CATMODE and CATFORMAT determined from catalog */
+
+  switch (lock_catalog (catalog, LCK_SOFT)) {
+  case 0:
+    fprintf (stderr, "ERROR: can't lock file %s\n", catalog[0].filename);
+    exit (1);
+  case 1:
+    if (!load_catalog (catalog, VERBOSE)) {
+      fprintf (stderr, "ERROR: failure loading catalog %s\n", catalog[0].filename);
+      exit (1);
+    }
+    if (VERBOSE) {
+      fprintf (stderr, "read %d stars from catalog file %s (%d measurements)\n", 
+	       catalog[0].Naverage, catalog[0].filename, catalog[0].Nmeasure);
+    }
+    return (TRUE);
+  case 2:
+    if (VERBOSE) fprintf (stderr, "no data in %s, skipping\n", catalog[0].filename);
+    return (FALSE);
+  default:
+    fprintf (stderr, "weird lock_catalog exit state\n");
+    exit (1);
+  }
+  return (FALSE);
+}
Index: /tags/uniphot-1-2/Ohana/src/uniphot/src/image-db.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/image-db.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/image-db.c	(revision 5424)
@@ -0,0 +1,27 @@
+# include "uniphot.h"
+
+void lock_image_db (FITS_DB *db, char *filename) {
+
+  /* lock the image catalog */
+  check_permissions (filename);
+
+  db[0].lockstate = LCK_XCLD;
+  db[0].timeout   = 3600.0;
+  fits_db_init (db);
+
+  if (!fits_db_lock (db, filename)) {
+    fprintf (stderr, "ERROR: can't lock image catalog\n");
+    exit (1);
+  }
+}
+
+void unlock_image_db (FITS_DB *db) {
+
+  mode_t mode;
+
+  fits_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);
+}
Index: /tags/uniphot-1-2/Ohana/src/uniphot/src/initialize.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/initialize.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/initialize.c	(revision 5424)
@@ -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: /tags/uniphot-1-2/Ohana/src/uniphot/src/liststats.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/liststats.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/liststats.c	(revision 5424)
@@ -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);
+
+  sortB (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];
+    }
+    sortD (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: /tags/uniphot-1-2/Ohana/src/uniphot/src/load_images.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/load_images.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/load_images.c	(revision 5424)
@@ -0,0 +1,13 @@
+# include "uniphot.h"
+
+int load_images (FITS_DB *db) {
+
+  if (VERBOSE) fprintf (stderr, "finding images\n");
+
+  if (db[0].dbstate == LCK_EMPTY) Shutdown ("ERROR: No images in catalog %s (1)", db[0].filename);
+
+  /* read entire db table */
+  if (!dvo_image_load (db, VERBOSE, FALSE)) Shutdown ("can't read image catalog %s", db[0].filename);
+
+  return (TRUE);
+}
Index: /tags/uniphot-1-2/Ohana/src/uniphot/src/misc.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/misc.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/misc.c	(revision 5424)
@@ -0,0 +1,128 @@
+# include "uniphot.h"
+
+void sort (unsigned int *X, int N) {
+
+  int l,j,ir,i;
+  unsigned 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 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: /tags/uniphot-1-2/Ohana/src/uniphot/src/plotstuff.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/plotstuff.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/plotstuff.c	(revision 5424)
@@ -0,0 +1,190 @@
+# 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) {
+
+  int i, InitSocket, status, addreslen;
+  struct sockaddr_un Address;
+  char temp[100], *display_name;
+  char socket_name[100];
+  FILE *f;
+  
+  active = N;
+  sprintf (socket_name, "/tmp/kapa%d", N);
+  sprintf (temp, "rm -f %s", socket_name);
+  system (temp);
+    
+  strcpy (Address.sun_path, socket_name); 
+  Address.sun_family = AF_UNIX; 
+  InitSocket = socket (AF_UNIX, SOCK_STREAM, 0); 
+  status = bind (InitSocket, &Address, sizeof (Address));
+  status = listen (InitSocket, 1);
+  
+  sprintf (temp, "kapa %s &", socket_name);
+# ifndef DEBUG
+  system (temp);
+# else  
+  fprintf (stderr, "start kapa, press return: %s\n", temp);
+  fscanf (stdin, "%d", &i);
+# endif
+  
+  addreslen =  sizeof (Address);
+  Xgraph[N] = accept (InitSocket, &Address, &addreslen);
+  if (Xgraph[N] < 0) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  }
+  else {
+    return (TRUE);
+  }
+  
+}
+
+void DonePlotting (Graphdata *graphmode, int N) {
+  char buffer[65], buffer2[65];
+
+  if (Xgraph[N] == 0) return;
+
+  write (Xgraph[N], "DBOX", 4);
+  sprintf (buffer, "%f %f %f %f", graphmode[0].xmin, graphmode[0].xmax, graphmode[0].ymin, graphmode[0].ymax);
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+
+  sprintf (buffer, "%s %s %s", "2222", "2222", "2222");
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+}
+
+void JpegPlot (Graphdata *graphmode, int N, char *filename) {
+  char buffer[65], buffer2[65];
+
+  if (Xgraph[N] == 0) return;
+
+  write (Xgraph[N], "PNGF", 4);
+  sprintf (buffer, "LEN: %11d", strlen (filename));
+  write (Xgraph[N], buffer, 16);
+  write (Xgraph[N], filename, strlen (filename));
+  read (Xgraph[N], buffer, 4);
+}
+
+void PSPlot (Graphdata *graphmode, int N, char *filename) {
+  char buffer[65], buffer2[65];
+
+  if (Xgraph[N] == 0) return;
+
+  write (Xgraph[N], "PSIT", 4);
+  sprintf (buffer, "LEN: %11d", strlen (filename));
+  write (Xgraph[N], buffer, 16);
+  write (Xgraph[N], filename, strlen (filename));
+  read (Xgraph[N], buffer, 4);
+}
+
+void PrepPlotting (int Npts, Graphdata *graphmode, int N) {
+
+  int i, status;
+  char buffer[128], buffer2[128];
+
+  active = N;
+  if (Npts < 1) return;
+
+  if (Xgraph[N] < 1) if (!open_graph(N)) return;
+
+  /* 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); 
+  
+  write (Xgraph[N], "ERAS", 4);
+  
+  /* tell kapa to look for the incoming image */
+  status = write (Xgraph[N], "PLOT", 4); 
+
+  /* send Xgraph[N] the plot details */
+  sprintf (buffer, "%8d %8d %d %d %d %d %f %f", 
+	   Npts, graphmode[0].style, 
+	   graphmode[0].ptype, graphmode[0].ltype, 
+	   graphmode[0].etype, graphmode[0].color, 
+	   graphmode[0].lweight, graphmode[0].size);
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+  
+  sprintf (buffer, "%f %f %f %f", 
+	   graphmode[0].xmin, graphmode[0].xmax, 
+	   graphmode[0].ymin, graphmode[0].ymax);
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+
+}
+
+void PlotLabel (char *string, int N) {
+
+  char buffer[32];
+
+  if (Xgraph[N] == 0) return;
+
+  write (Xgraph[N], "LABL", 4);
+  sprintf (buffer, " %6d %6d", strlen (string), 2);
+  write (Xgraph[N], buffer, 16);
+  write (Xgraph[N], string, strlen (string));
+}
+
+void PlotVector (int Npts, double *vect, int mode, int N) {
+
+  float *values;
+  int i, Nbytes;
+
+  active = N;
+  if (Npts < 1) return;
+
+  ALLOCATE (values, float, Npts);
+  for (i = 0; i < Npts; i++) {
+    values[i] = vect[i];
+  }
+
+  Nbytes = Npts * sizeof (float);
+  write (Xgraph[N], values, Nbytes);
+  free (values);
+
+}
+
+/* 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: /tags/uniphot-1-2/Ohana/src/uniphot/src/subset_images.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/subset_images.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/subset_images.c	(revision 5424)
@@ -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 = fits_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].source);
+    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 ++;
+  }
+
+  fits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, keep, Nkeep);
+  return (TRUE);
+}
Index: /tags/uniphot-1-2/Ohana/src/uniphot/src/time.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/time.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/time.c	(revision 5424)
@@ -0,0 +1,313 @@
+# include "uniphot.h"
+
+# define FORMAT_DAYS    1
+# define FORMAT_HOURS   2
+# define FORMAT_MINUTES 3
+# define FORMAT_SECONDS 4
+# define FORMAT_JD      5
+# define FORMAT_DATE    6
+
+/***** 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);
+}
+
+/**********/
+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, unsigned int *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 (unsigned long second) {
+
+  double jd;
+  
+  jd = second/86400.0 + 2440587.5;
+  return (jd);
+}
+
+/**********/
+unsigned long int jd_to_sec (double jd) {
+
+  unsigned long int second;
+
+  second = (jd - 2440587.5)*86400;
+  return (second);
+}
+
+/**********/
+char *sec_to_date (unsigned long 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 *****/
+unsigned long date_to_sec (char *date) {
+  
+  unsigned long 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;
+
+  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: /tags/uniphot-1-2/Ohana/src/uniphot/src/uniphot.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/uniphot.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/uniphot.c	(revision 5424)
@@ -0,0 +1,61 @@
+# include "uniphot.h"
+
+int main (int argc, char **argv) {
+
+  int i, Ntgroup, Nsgroup;
+  Group *tgroup, *sgroup;
+  ImageLink *imlinks;
+  FITS_DB db;
+
+  /* get configuration info, args, lockfile */
+  initialize (argc, argv);
+
+  set_db (&db);
+  lock_image_db (&db, ImageCat);
+
+  /* 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);
+  unlock_image_db (&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: /tags/uniphot-1-2/Ohana/src/uniphot/src/update.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/update.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/update.c	(revision 5424)
@@ -0,0 +1,106 @@
+# 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 = fits_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_PS -= sgroup[i].M;
+    }
+  }
+
+  /** write image table **/
+  dvo_image_update (db, VERBOSE);
+
+  /** 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];
+    if (!gcatalog (&catalog)) continue;
+
+    fits_scan (&catalog.header, "RA0", "%lf",  1, &Rmin);
+    fits_scan (&catalog.header, "RA1", "%lf",  1, &Rmax);
+    fits_scan (&catalog.header, "DEC0", "%lf", 1, &Dmin);
+    fits_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)); 
+    wcatalog (&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: /tags/uniphot-1-2/Ohana/src/uniphot/src/update_catalog.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/update_catalog.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/update_catalog.c	(revision 5424)
@@ -0,0 +1,35 @@
+# include "uniphot.h"
+
+void update_dvo_catalog (Catalog *catalog, Group *sgroup, int warn) {
+
+  int i, j, m, found;
+  int Primary, Nsec, Nsecfilt;
+  float *Mp;
+  PhotCode *code;
+
+  Primary = (photcode[0].type == PHOT_PRI);
+  Nsec = GetPhotcodeNsec (photcode[0].code);
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  found = 0;    
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    
+    Mp = Primary ? &catalog[0].average[i].M_PS : &catalog[0].secfilt[i*Nsecfilt+Nsec].M_PS;
+    if (*Mp != NO_MAG) *Mp += 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].source);
+      if (code == NULL) continue;
+      if (code[0].type != PHOT_DEP) continue;
+      if (code[0].equiv != photcode[0].code) continue;
+      catalog[0].measure[m].Mcal_PS -= 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: /tags/uniphot-1-2/Ohana/src/uniphot/src/wcatalog.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/wcatalog.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/wcatalog.c	(revision 5424)
@@ -0,0 +1,31 @@
+# include "uniphot.h"
+
+void wcatalog (Catalog *catalog) {
+
+  /* CATMODE and CATFORMAT determined from catalog */
+
+  /** write out catalog, free memory **/
+  if (!save_catalog (catalog, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure saving catalog\n");
+    exit (1);
+  }
+      
+  if (catalog[0].Naverage) {
+    free (catalog[0].average); 
+    catalog[0].Naverage = 0;
+  }
+  if (catalog[0].Nmeasure) {
+    free (catalog[0].measure); 
+    catalog[0].Nmeasure = 0;
+  }
+  if (catalog[0].Nmissing) {
+    free (catalog[0].missing); 
+    catalog[0].Nmissing = 0;
+  }
+  if (catalog[0].Nsecfilt) {
+    free (catalog[0].secfilt); 
+    catalog[0].Nsecfilt = 0;
+  }
+  fits_free_header (&catalog[0].header);
+  unlock_catalog (catalog);
+}
Index: /tags/uniphot-1-2/Ohana/src/uniphot/src/wimages.c
===================================================================
--- /tags/uniphot-1-2/Ohana/src/uniphot/src/wimages.c	(revision 5424)
+++ /tags/uniphot-1-2/Ohana/src/uniphot/src/wimages.c	(revision 5424)
@@ -0,0 +1,42 @@
+# include "uniphot.h"
+
+/***** this needs to be changed to use the dvo autocode structures !!! */
+
+void wimages (Image *image, int Nimage) {
+
+  int status, mode;
+  char line[256];
+  FILE *f;
+  Header header;
+
+  /* make backup */
+  sprintf (line, "cp %s %s~", ImageCat, ImageCat);
+  if (system (line)) {
+    fprintf (stderr, "ERROR: failed to make backup copy of image table\n");
+    exit (1);
+  }
+
+  /* load image catalog */
+  f = fopen (ImageCat, "r+");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open image catalog file to append: %s\n", ImageCat);
+    exit (1);
+  }
+  if (!fits_fread_header (f, &header)) {
+    fprintf (stderr, "ERROR: can't read header %s\n", ImageCat);
+    exit (1);
+  }
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (ImageCat, mode);
+  fseek (f, header.size, SEEK_SET);
+
+  /* write image data */
+  if (VERBOSE) fprintf (stderr, "writing out %d images\n", Nimage);
+  status = Fwrite (image, sizeof(Image), Nimage, f, "image");
+  if (status != Nimage) {
+    fprintf (stderr, "ERROR: failed writing data to image catalog\n");
+    exit (1);
+  }
+  fclose (f);
+
+}
