Index: /trunk/Ohana/src/libohana/dvo/def/old/template.c
===================================================================
--- /trunk/Ohana/src/libohana/dvo/def/old/template.c	(revision 3527)
+++ /trunk/Ohana/src/libohana/dvo/def/old/template.c	(revision 3527)
@@ -0,0 +1,242 @@
+# include "fitsdb.h"
+
+/* allocate db and components (not data) */
+$NAME_DB *$NAME_DB_Allocate (dbMode mode) {
+  
+  $NAME_DB *db;
+
+  ALLOCATE (db, $NAME_DB, 1);
+  ALLOCATE (db[0].phu,    Header, 1);
+  ALLOCATE (db[0].header, Header, 1);
+  if (mode == DB_VIRTUAL) {
+    ALLOCATE (db[0].vtable, VTable, 1);
+    db[0].ftable = NULL;
+  } else {
+    ALLOCATE (db[0].ftable, FTable, 1);
+    db[0].vtable = NULL;
+  }
+  return (db);
+}
+
+/* Create a new database table (in memory, not on disk) */
+/* we always use BINTABLE for the db tables */
+$NAME_DB *$NAME_DB_Init (dbMode mode) {
+
+  $NAME_DB *db;
+
+  db = $NAME_DB_Allocate (mode);
+
+  /* create the empty PHU */
+  fits_init_header (db[0].phu);    
+  db[0].phu[0].extend = TRUE;
+  fits_create_header (db[0].phu);
+  fits_print (db[0].phu, "NEXTEND", "%d", 1, 1);
+
+  /* create the basic table header */
+  fits_create_table_header (db[0].header, "BINTABLE", EXTNAME);
+  /** TABLE DEFINITION **/ 
+
+  /* create the initial table data */
+  if (mode == DB_VIRTUAL) {
+    fits_create_vtable (db[0].header, db[0].vtable, 0);
+  } else {
+    fits_create_table (db[0].header, db[0].ftable);
+  }
+
+  db[0].f = (FILE *) NULL;
+  db[0].filename = (char *) NULL;
+  db[0].lockreq = LCK_UNLOCK;
+  db[0].lockstate = LCK_UNLOCK;
+
+  return (db);
+}
+
+$NAME_DB *$NAME_DB_Load (char *filename, int lockreq) {
+
+  int i, Nx, Ny, Nc;
+  int lockstate;
+  char *byte, tmp;
+  FILE *f;
+  $NAME_DB *db;
+
+  /* filename is not defined */
+  if (filename == (char *) NULL) {
+    fprintf (stderr, "db file is not valid\n");
+    return (NULL);
+  }
+
+  /* lock database (soft) */
+  f = fsetlockfile (filename, TIMEOUT, lockreq, &lockstate);
+
+  /* lock set failure */
+  if ((f == (FILE *) NULL) && (lockstate != LCK_EMPTY)) {
+    fprintf (stderr, "can't set lock on %s\n", filename);
+    return (NULL);
+  }
+
+  /* this can only happen if lockreq is SOFT (file does not exist) */
+  if (lockstate == LCK_EMPTY) {
+    db = $NAME_DB_Init (DB_TOTAL);
+    db[0].lockreq = lockreq;
+    db[0].lockstate = lockstate;
+    return (db);
+  }
+    
+  /* build db data structure */
+  db = $NAME_DB_Allocate (DB_TOTAL);
+  db[0].f = f;
+  db[0].filename = filename;
+  db[0].lockreq = lockreq;
+  db[0].lockstate = lockstate;
+  
+  /* init & load in table data */
+  if (!fits_fread_header (f, db[0].phu)) { }
+  /* validate PHU vs FITS DB rules */
+
+  if (!fits_fread_header (f, db[0].header)) { }
+  /* validate header vs schema */
+
+  if (!fits_fread_ftable_data (f, db[0].ftable)) { }
+
+  fits_scan (db[0].header, "NAXIS1",  "%d", 1, &Nx);
+  fits_scan (db[0].header, "NAXIS2",  "%d", 1, &Ny);
+  fits_scan (db[0].header, "TFIELDS", "%d", 1, &Nc);
+
+  db[0].Nbyte = Nx;
+  db[0].Nrows = Ny;
+  db[0].Ncols = Nc;
+
+  $NAME_DB_Convert (db);
+
+  db[0].data = ($NAME *)db[0].ftable[0].buffer;
+  return (db);
+}
+
+$NAME_DB *$NAME_DB_Loadset (char *filename, int lockreq, int start, int Nrows) {
+
+  int i, Nx, Ny, Nc;
+  int lockstate;
+  char *byte, tmp;
+  FILE *f;
+  $NAME_DB *db;
+
+  /* filename is not defined */
+  if (filename == (char *) NULL) {
+    fprintf (stderr, "db file is not valid\n");
+    return (NULL);
+  }
+
+  /* lock database (soft) */
+  f = fsetlockfile (filename, TIMEOUT, lockreq, &lockstate);
+
+  /* lock set failure */
+  if ((f == (FILE *) NULL) && (lockstate != LCK_EMPTY)) {
+    fprintf (stderr, "can't set lock on %s\n", filename);
+    return (NULL);
+  }
+
+  /* this can only happen if lockreq is SOFT (file does not exist) */
+  if (lockstate == LCK_EMPTY) {
+    /* file is empty; if we requested any data, it is not there */
+    if (Nrows > 0) return (NULL);
+    db = $NAME_DB_Init (DB_VIRTUAL);
+    db[0].lockreq = lockreq;
+    db[0].lockstate = lockstate;
+    return (db);
+  }
+    
+  /* build db data structure */
+  db = $NAME_DB_Allocate (DB_VIRTUAL);
+  db[0].f = f;
+  db[0].filename = filename;
+  db[0].lockreq = lockreq;
+  db[0].lockstate = lockstate;
+  
+  /* init & load in table data */
+  if (!fits_fread_header (f, db[0].phu)) { }
+  /* validate PHU vs FITS DB rules */
+
+  if (!fits_fread_header (f, db[0].header)) { }
+  /* validate header vs schema */
+
+  if (!fits_fread_vtable_range (f, db[0].vtable, start, Nrows)) { }
+
+  fits_scan (db[0].header, "TFIELDS", "%d", 1, &Nc);
+  db[0].Nbyte = db[0].header[0].Naxis[0];
+  db[0].Nrows = db[0].header[0].Naxis[1];
+  db[0].Ncols = Nc;
+
+  $NAME_DB_Convert (db);
+
+  /** this does not make sense; how do we access vtable data? **/
+  /** db[0].data = ($NAME *)db[0].ftable.buffer; **/
+  return (db);
+}
+
+/* write out complete db */
+int $NAME_DB_Save ($NAME_DB *db) {
+
+  make_backup (db[0].filename);
+
+  $NAME_DB_Convert (db);
+
+  Fseek (db[0].f, 0, SEEK_SET);
+  if (!fits_fwrite_header  (db[0].f, db[0].phu)) { }
+  if (!fits_fwrite_header  (db[0].f, db[0].header)) { }
+  if (!fits_fwrite_table   (db[0].f, db[0].ftable)) { }
+
+  $NAME_DB_Free (db);
+
+  fclearlockfile (db[0].filename, db[0].f, db[0].lockreq, &db[0].lockstate);
+  return (TRUE);
+}
+
+/* write out complete headers and specific rows of db */
+int $NAME_DB_Saveset ($NAME_DB *db) {
+
+  $NAME_DB_Convert (db);
+
+  Fseek (db[0].f, 0, SEEK_SET);
+  if (!fits_fwrite_header  (db[0].f, db[0].phu)) { }
+  if (!fits_fwrite_header  (db[0].f, db[0].header)) { }
+  if (!fits_fwrite_vtable  (db[0].f, db[0].vtable)) { }
+
+  $NAME_DB_Free (db);
+
+  fclearlockfile (db[0].filename, db[0].f, db[0].lockreq, &db[0].lockstate);
+  return (TRUE);
+}
+
+$NAME_DB *$NAME_DB_Free ($NAME_DB *db) {
+
+  fits_free_header (db[0].phu);
+  fits_free_header (db[0].header);
+  fits_free_table  (db[0].ftable);
+  fits_free_vtable (db[0].vtable);
+  return (NULL);
+}
+
+/** this function does disk <--> memory conversion **/
+void $NAME_DB_Convert ($NAME_DB *db) {
+  
+  int i, Nx;
+  char *byte, tmp;
+
+  Nx = db[0].Nbyte;
+
+  if (db[0].ftable != NULL) {
+    for (i = 0; i < db[0].Nrows; i++) {
+      byte = &db[0].ftable[0].buffer[i*Nx];
+      /** BYTE SWAP **/
+    }
+  }
+
+  if (db[0].vtable != NULL) {
+    for (i = 0; i < db[0].vtable[0].Nrow; i++) {
+      byte = db[0].vtable[0].buffer[i];
+      /** BYTE SWAP **/
+    }
+  }
+
+}
+
Index: /trunk/Ohana/src/libohana/dvo/def/old/template.h
===================================================================
--- /trunk/Ohana/src/libohana/dvo/def/old/template.h	(revision 3527)
+++ /trunk/Ohana/src/libohana/dvo/def/old/template.h	(revision 3527)
@@ -0,0 +1,39 @@
+# define TIMEOUT $TIMEOUT
+# define EXTNAME "$EXTNAME"
+
+/** STRUCT DEFINITION **/
+
+typedef struct {
+  FILE *f;
+  char *filename;
+
+  Header *phu;
+  Header *header;
+  FTable *ftable;
+  VTable *vtable;
+
+  int Nrows;
+  int Ncols;
+  int Nbyte;
+
+  int Nphu_disk;    // original size of PHU
+  int Nheader_disk; // original size of header 
+  int Nrows_disk;   // original number of rows
+
+  int lockstate;
+  int lockreq;
+  int virtual;
+
+  $NAME *data;
+} $NAME_DB;
+
+$NAME_DB *$NAME_DB_Allocate (dbMode mode);
+$NAME_DB *$NAME_DB_Init (dbMode mode);
+$NAME_DB *$NAME_DB_Load (char *filename, int lockreq);
+$NAME_DB *$NAME_DB_Loadset (char *filename, int lockreq, int start, int Nrows);
+$NAME_DB *$NAME_DB_Free ($NAME_DB *db);
+
+void $NAME_DB_Convert ($NAME_DB *db);
+
+int $NAME_DB_Saveset ($NAME_DB *db);
+int $NAME_DB_Save ($NAME_DB *db);
Index: /trunk/Ohana/src/libohana/dvo/def/old/test.d
===================================================================
--- /trunk/Ohana/src/libohana/dvo/def/old/test.d	(revision 3527)
+++ /trunk/Ohana/src/libohana/dvo/def/old/test.d	(revision 3527)
@@ -0,0 +1,10 @@
+TIMEOUT 300
+
+NAME TEST
+EXTNAME TEST
+STRUCT Test
+FILE test
+
+FIELD time,   double,   data point in time, seconds 
+FIELD length, int,      file length,        bytes 
+FIELD name,   char[23], file name,           
Index: /trunk/Ohana/src/perl/src/imstats.mana
===================================================================
--- /trunk/Ohana/src/perl/src/imstats.mana	(revision 3527)
+++ /trunk/Ohana/src/perl/src/imstats.mana	(revision 3527)
@@ -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
