Index: trunk/Ohana/src/libdvo/include/dvo.h
===================================================================
--- trunk/Ohana/src/libdvo/include/dvo.h	(revision 34749)
+++ trunk/Ohana/src/libdvo/include/dvo.h	(revision 34844)
@@ -322,8 +322,17 @@
   int *NBAND;
 
-  double   **ra;
-  double  **dec;
-  int    **cell;
-  char  ***name;
+  double   **ra; // RA of projection cell center
+  double  **dec; // DEC of projection cell center
+  int    **cell; // zone,band -> proj cell sequence
+  char  ***name; // projection cell name
+  
+  int NX_SUB;
+  int NY_SUB;
+  double dPix;
+
+  double **Xo;
+  double **Yo;
+  int **dX;
+  int **dY;
 } BoundaryTree;
 
@@ -496,4 +505,5 @@
 float PhotKronInst (Measure *measure);
 float PhotKronAve (PhotCode *code, Average *average, SecFilt *secfilt);
+float PhotKronAveErr (PhotCode *code, Average *average, SecFilt *secfilt);
 
 float PhotZeroPoint (Measure *measure, Average *average, SecFilt *secfilt);
@@ -701,4 +711,5 @@
 int BoundaryTreeSave(char *filename, BoundaryTree *tree);
 BoundaryTree *BoundaryTreeLoad(char *filename);
+int BoundaryTreeProjection (double *x, double *y, double r, double d, BoundaryTree *tree, int zone, int band);
 
 void dvo_average_init (Average *average);
Index: trunk/Ohana/src/libdvo/src/BoundaryTree.c
===================================================================
--- trunk/Ohana/src/libdvo/src/BoundaryTree.c	(revision 34749)
+++ trunk/Ohana/src/libdvo/src/BoundaryTree.c	(revision 34844)
@@ -47,4 +47,8 @@
   gfits_scan (&header, "DEC_ORI", "%lf", 1, &tree->DEC_origin);
   gfits_scan (&header, "DEC_OFF", "%lf", 1, &tree->DEC_offset);
+
+  gfits_scan (&header, "NX_SUB", "%d", 1, &tree->NX_SUB);
+  gfits_scan (&header, "NY_SUB", "%d", 1, &tree->NY_SUB);
+  gfits_scan (&header, "PIXSCALE", "%lf", 1, &tree->dPix);
 
   ftable.header = &theader;
@@ -75,10 +79,18 @@
     ALLOCATE (tree->ra,   double *, tree->Nzone);
     ALLOCATE (tree->dec,  double *, tree->Nzone);
-    ALLOCATE (tree->cell, int *, tree->Nzone);
-    ALLOCATE (tree->name, char **, tree->Nzone);
+    ALLOCATE (tree->Xo,   double *, tree->Nzone);
+    ALLOCATE (tree->Yo,   double *, tree->Nzone);
+    ALLOCATE (tree->dX,      int *, tree->Nzone);
+    ALLOCATE (tree->dY,      int *, tree->Nzone);
+    ALLOCATE (tree->cell,    int *, tree->Nzone);
+    ALLOCATE (tree->name,  char **, tree->Nzone);
     for (i = 0; i < tree->Nzone; i++) {
       ALLOCATE (tree->ra[i],   double, tree->Nband[i]);
       ALLOCATE (tree->dec[i],  double, tree->Nband[i]);
-      ALLOCATE (tree->cell[i], int,    tree->Nband[i]);
+      ALLOCATE (tree->Xo[i],   double, tree->Nband[i]);
+      ALLOCATE (tree->Yo[i],   double, tree->Nband[i]);
+      ALLOCATE (tree->dX[i],      int, tree->Nband[i]);
+      ALLOCATE (tree->dY[i],      int, tree->Nband[i]);
+      ALLOCATE (tree->cell[i],    int, tree->Nband[i]);
       ALLOCATE (tree->name[i], char *, tree->Nband[i]);
       for (j = 0; j < tree->Nband[i]; j++) {
@@ -102,4 +114,8 @@
     GET_COLUMN_NEW(band,  "BAND",        int);
     GET_COLUMN_NEW(index, "INDEX",       int);
+    GET_COLUMN_NEW(Xo,    "X_CENT",      double);
+    GET_COLUMN_NEW(Yo,    "Y_CENT",      double);
+    GET_COLUMN_NEW(dX,    "X_GRID",      int);
+    GET_COLUMN_NEW(dY,    "Y_GRID",      int);
     GET_COLUMN_NEW(name,  "NAME",        char); // XXX how is this done?
     gfits_free_header (&theader);
@@ -113,4 +129,8 @@
       tree->ra[nz][nb] = R[i];
       tree->dec[nz][nb] = D[i];
+      tree->Xo[nz][nb] = Xo[i];
+      tree->Yo[nz][nb] = Yo[i];
+      tree->dX[nz][nb] = dX[i];
+      tree->dY[nz][nb] = dY[i];
       tree->cell[nz][nb] = i; // XXX ?
       memcpy(tree->name[nz][nb], &name[i*BOUNDARY_TREE_NAME_LENGTH], BOUNDARY_TREE_NAME_LENGTH);
@@ -121,4 +141,8 @@
     free (zone  );
     free (band  );
+    free (Xo    );
+    free (Yo    );
+    free (dX    );
+    free (dY    );
     free (index );
     free (name  );
@@ -165,4 +189,8 @@
   gfits_modify (&header, "DEC_ORI", "%lf", 1, tree->DEC_origin);
   gfits_modify (&header, "DEC_OFF", "%lf", 1, tree->DEC_offset);
+
+  gfits_modify (&header, "NX_SUB", "%d", 1, tree->NX_SUB);
+  gfits_modify (&header, "NY_SUB", "%d", 1, tree->NY_SUB);
+  gfits_modify (&header, "PIXSCALE", "%lf", 1, tree->dPix);
 
   gfits_fwrite_header  (f, &header);
@@ -223,4 +251,8 @@
     gfits_define_bintable_column (&theader, "J", "BAND", "band sequence number", "none", 1.0, 0.0);
     gfits_define_bintable_column (&theader, "J", "INDEX","cell index", "none", 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "D", "X_CENT", "projection cell center pixel", "none", 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "D", "Y_CENT", "projection cell center pixel", "none", 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "J", "X_GRID", "skycell grid spacing", "none", 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "J", "Y_GRID", "skycell grid spacing", "none", 1.0, 0.0);
     gfits_define_bintable_column (&theader, fmt, "NAME", "cell name", "none", 1.0, 0.0);
 
@@ -240,4 +272,8 @@
     int    *band          ; ALLOCATE (band,  int,    Ncell);
     int    *index         ; ALLOCATE (index, int,    Ncell);
+    double *Xo            ; ALLOCATE (Xo,    double, Ncell);
+    double *Yo            ; ALLOCATE (Yo,    double, Ncell);
+    int    *dX            ; ALLOCATE (dX,    int,    Ncell);
+    int    *dY            ; ALLOCATE (dY,    int,    Ncell);
     char   *name          ; ALLOCATE (name,  char,   Ncell*BOUNDARY_TREE_NAME_LENGTH);
 
@@ -251,4 +287,8 @@
 	R[i]     = tree->ra[nz][nb];
 	D[i]     = tree->dec[nz][nb];
+	Xo[i]    = tree->Xo[nz][nb];
+	Yo[i]    = tree->Yo[nz][nb];
+	dX[i]    = tree->dX[nz][nb];
+	dY[i]    = tree->dY[nz][nb];
 	zone[i]  = nz;
 	band[i]  = nb;
@@ -265,4 +305,8 @@
     gfits_set_bintable_column (&theader, &ftable, "BAND",  band,  Ncell);
     gfits_set_bintable_column (&theader, &ftable, "INDEX", index, Ncell);
+    gfits_set_bintable_column (&theader, &ftable, "X_CENT", Xo,   Ncell);
+    gfits_set_bintable_column (&theader, &ftable, "Y_CENT", Yo,   Ncell);
+    gfits_set_bintable_column (&theader, &ftable, "X_GRID", dX,   Ncell);
+    gfits_set_bintable_column (&theader, &ftable, "Y_GRID", dY,   Ncell);
     gfits_set_bintable_column (&theader, &ftable, "NAME",  name,  Ncell);
 
@@ -272,4 +316,8 @@
     free (band  );
     free (index );
+    free (Xo    );
+    free (Yo    );
+    free (dX    );
+    free (dY    );
     free (name  );
 
@@ -318,2 +366,58 @@
 }
 
+
+// projection = TAN
+// need Ro, Do, Xo, Yo, dPix
+
+int BoundaryTreeProjection (double *x, double *y, double r, double d, BoundaryTree *tree, int zone, int band) {
+
+    double Xo = tree->Xo[zone][band];
+    double Yo = tree->Yo[zone][band];
+    double Ro = tree->ra[zone][band];
+    double Do = tree->dec[zone][band];
+    double dPix = tree->dPix;
+
+    // this block only depends on Ro, Do
+
+    double sdp  = sin(RAD_DEG*Do);
+    double cdp  = cos(RAD_DEG*Do);
+    double salp = sin(RAD_DEG*(r - Ro));
+    double calp = cos(RAD_DEG*(r - Ro));
+    double sdel = sin(RAD_DEG*d);
+    double cdel = cos(RAD_DEG*d);
+    
+    double stht = sdel*sdp + cdel*cdp*calp;    /* sin(theta) */
+    double sphi = cdel*salp;                   /* = cos(theta)*sin(phi) */
+    double cphi = cdel*sdp*calp - sdel*cdp;    /* = cos(theta)*cos(phi) */
+
+    // defines the TAN projection (one of zenithal projections available, libdvo/src/coordops.c
+    // R = cot (theta) = cos(theta) / sin(theta)
+    double L, M;
+    if (stht == 0) {
+	double Rc = hypot(sphi, cphi);
+	L = 180.0 * sphi / Rc;
+	M = 180.0 * cphi / Rc;
+    } else {
+	L = +DEG_RAD * sphi / stht;
+	M = -DEG_RAD * cphi / stht;
+    }
+
+    // scale, rotation, parity:
+    // rotation == 0.0 (pc1_1 == pc2_2 == 1.0, pc1_2 = pc2_1 = 0.0)
+
+    // if there were rotation or parity:
+    // Ro = (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+    // Xo = (coords[0].pc2_2*L - coords[0].pc1_2*M) / Ro;
+    // Yo = (coords[0].pc1_1*M - coords[0].pc2_1*L) / Ro;
+
+    double X = L;
+    double Y = M;
+
+    // scale is dPix
+
+    *x = Xo - X / dPix;
+    *y = Yo + Y / dPix;
+    
+    return TRUE;
+}
+
Index: trunk/Ohana/src/libdvo/src/dbExtractAverages.c
===================================================================
--- trunk/Ohana/src/libdvo/src/dbExtractAverages.c	(revision 34749)
+++ trunk/Ohana/src/libdvo/src/dbExtractAverages.c	(revision 34844)
@@ -233,4 +233,8 @@
 	  break;
 
+	case MAG_KRON_ERR:
+	  value.Flt = PhotKronAveErr (field->photcode, average, secfilt);
+	  break;
+
 	case MAG_20:
 	  value.Flt = PhotM20 (field->photcode, average, secfilt);
Index: trunk/Ohana/src/libdvo/src/dvo_catalog_split.c
===================================================================
--- trunk/Ohana/src/libdvo/src/dvo_catalog_split.c	(revision 34749)
+++ trunk/Ohana/src/libdvo/src/dvo_catalog_split.c	(revision 34844)
@@ -863,5 +863,5 @@
     first  = 0;                    // first row in memory to write
     start  = catalog[0].Nsecf_off; // first disk row to write
-    Nitems = catalog[0].Nsecf_mem;
+    Nitems = catalog[0].Naverage*Nsecfilt;
     Nrows  = Nitems - first;
 
Index: trunk/Ohana/src/libdvo/src/dvo_photcode_ops.c
===================================================================
--- trunk/Ohana/src/libdvo/src/dvo_photcode_ops.c	(revision 34749)
+++ trunk/Ohana/src/libdvo/src/dvo_photcode_ops.c	(revision 34844)
@@ -572,4 +572,16 @@
 }
 
+float PhotKronAveErr (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  int Ns;
+  float dMkron;
+
+  if (code == NULL) return NAN;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  dMkron = (Ns == -1) ? NAN : secfilt[Ns].dMkron;
+  return (dMkron);
+}
+
 float PhotAveFluxPSF (PhotCode *code, Average *average, SecFilt *secfilt) {
 
