/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.COPYRIGHT   (c)  1996-2010  European Southern Observatory
.IDENT       tbl2bdf.c
.LANGUAGE    C
.AUTHOR      P. Grosbol ESO/IPG
.KEYWORDS    3D-table, convert, image
.ENVIRON     MIDAS
.PURPOSE     Convert a 3D-table column to a image file

.VERSION     1.0  1996-Apr-12 : Creation, PJG

 100803		last modif
------------------------------------------------------------------------*/

#include   <math.h>                  /* Mathematical macros             */
#include   <string.h>                /* String handling macros          */
#include   <stdlib.h>      
#include   <stdio.h>

#include   "midas_def.h"             /* MIDAS definitions               */

#define    MAXDIM                 16  /* Max. image dimension            */
#define    MXPAR                 64  /* Max. char. in parameter string  */
#define    MXNAME               129  /* Max. length of file name        */

int main()

{
char     *pc, *buf, *cstart, *cstep, *cunit;
char     col[MXPAR], row[MXPAR], tname[MXPAR], pfix[MXPAR];
char     dim[MXPAR], coor[MXPAR], iname[MXNAME], text[MXNAME];
char     ident[MXPAR];

int      fid, tid, nident, ndim, ncol, nstr, nstp, nrlo, nrhi;
int      n, err, nr, nb, ns, iva, inull, sf, dt_double;
int      mcol, mrow, msort, macol, marow;
int      dt, dtdim, items, msize, maxis, dtcol;
int      mident, mstr, mstp, dtstr, dtstp;
int      rowcount, npix[MAXDIM], kunit[4];

float    *fbuf, f, cut[4];

double   *dbuf, d, cl, ch, step[MAXDIM], start[MAXDIM];



dbuf = (double *) 0;
fbuf = (float *) 0;
rowcount = 0;

SCSPRO("TBL2BDF");                   /* initiate MIDAS environment    */

/*  get table name and open it  */

  err = SCKGETC("IN_A", 1, MXPAR-1, &iva, tname);
  err = TCTOPN(tname, F_I_MODE, &tid);
  err = TCIGET(tid, &mcol, &mrow, &msort, &macol, &marow);

/*  get name of column which should be converted to an image */

  err = SCKGETC("INPUTC", 1, MXPAR-1, &iva, col);
  err = TCCSER(tid, col, &ncol);
  err = TCBGET(tid, ncol, &dtcol, &items, &nb);
  dt_double = (dtcol == D_R8_FORMAT);

/*  get range of rows to convert  */

  err = SCKGETC("ROW", 1, MXPAR-1, &iva, row);
  nrlo = 1; nrhi = mrow;
  if (row[0] != '*') {
     nr = atol(strtok(row, ","));
     nr = (nr<1) ? 1 : ((mrow<nr) ? mrow : nr);
     nrlo = nrhi = nr;
     if ((pc = strtok(NULL, ","))) nr = atol(pc);
     nrhi = (nr<nrlo) ? nrlo : ((mrow<nr) ? mrow : nr);
   }

/*  get dimensions of image  */

  err = SCKGETC("DIM", 1, MXPAR-1, &iva, dim);
  maxis = 1; npix[0] = msize = items; ndim = -1;
  if (dim[0] == ':' || dim[0] == '#') {
     err = TCCSER(tid, dim, &ndim);
     err = TCBGET(tid, ndim, &dtdim, &maxis, &iva);
     if ((dtdim != D_I4_FORMAT) && (dtdim != D_I2_FORMAT)) {
	TCTCLO(tid);
	SCETER(1, "Error: Wrong data type of dimension column");
     }
   }
  else if (dim[0] != '*') {
     maxis = 0;
     npix[maxis++] = atol(strtok(dim, ","));
     while ((pc = strtok(NULL, ","))) npix[maxis++] = atol(pc);
     msize = 1;
     for (n=0; n<maxis && 0<npix[n]; n++)  msize *= npix[n];
     if (n<maxis && npix[n]<1) {
	TCTCLO(tid);
	SCETER(2, "Error: Negative no. of pixels for axis specified");
      }
   }
  if (MAXDIM<maxis) {
     TCTCLO(tid);
     SCETER(3, "Error: Too high a dimension specified");
   }

/*  get coordinates for image  */

  err = SCKGETC("COOR", 1, MXPAR-1, &iva, coor);
  for (n=0; n<maxis; n++) start[n] = step[n] = 1.0;
  nstr = nstp = -1;
  if (coor[0] == ':' || coor[0] == '#') {
     cstart = strtok(coor, ",");
     cstep  = strtok(NULL, ",");
     err = TCCSER(tid, cstart, &nstr);
     err = TCBGET(tid, nstr, &dtstr, &mstr, &iva);
     err = TCCSER(tid, cstep, &nstp);
     err = TCBGET(tid, nstp, &dtstp, &mstp, &iva);
     if (maxis!=mstr && maxis!=mstp) {
	TCTCLO(tid);
	if (maxis!=mstr)
	  sprintf(text,"Error: Inconsistent size of column >%s<",cstart);
	else
	  sprintf(text,"Error: Inconsistent size of column >%s<",cstep);
	SCETER(4, text);
      }
   }
  else if (coor[0] != '*') {
     n = 0;
     start[n++] = atof(strtok(coor, ","));
     while ((pc=strtok(NULL, ",")) && n<maxis) start[n++] = atof(pc);
     n = 0;
     while ((pc=strtok(NULL, ",")) && n<maxis) step[n++] = atof(pc);
     for (n=0; n<maxis; n++)
       if (step[n]==0.0) {
	  step[n] = 1.0;
	  SCTPUT("Warning: Zero step size set to 1.0");
	}
   }

/*  get prefix for image names  */

  err = SCKGETC("PREFIX", 1, MXPAR-1, &iva, pfix);

/*  check if :IDENT column exist  */

  err = TCCSER(tid, ":IDENT", &nident);
  if (0<nident) {
     err = TCBGET(tid, nident, &dt, &mident, &iva);
     if (dt != D_C_FORMAT) nident = -1;
     if (MXPAR<=mident) mident = MXPAR - 1;
   }
  cunit = "                ";

/*  allocate memory for image   */

  buf = (char *) calloc(nb, 1);
  if (!buf) {
     TCTCLO(tid);
     SCETER(5, "Error: cannot allocate buffer");
   }
  if (dt_double) dbuf = (double *) buf; else fbuf = (float *) buf;

/*  go through specified range of rows    */

  for (nr=nrlo; nr<=nrhi; nr++) {
     err = TCSGET(tid, nr, &sf);        /* check if row is selected */
     if (!sf) 
        {
        sprintf(text,"row %d not selected - skipped...",nr);
        SCTPUT(text);
        continue;
        }
     else
       rowcount ++;

/*  read 3D-table element   */

     if (dt_double) {
       err = TCARDD(tid, nr, ncol, 1, items, dbuf);
       cl = ch = dbuf[0];
       for (n=0; n<items; n++) {
	  d = dbuf[n];
	 if (d<cl) cl = d; else if (ch<d) ch = d;
	}
     }
     else {
       err = TCARDR(tid, nr, ncol, 1, items, fbuf);
       cl = ch = fbuf[0];
       for (n=0; n<items; n++) {
	  f = fbuf[n];
	 if (f<cl) cl = f; else if (ch<f) ch = f;
	}
     }

/*  read dimension etc. for 3D table element if not constant */

    if (0<ndim) {
       err = TCARDI(tid, nr, ndim, 1, maxis, npix);
       msize = 1;
       for (n=0; n<maxis && 0<npix[n]; n++) msize *= npix[n];
       if (n<maxis && npix[n]<1) {
	  sprintf(text,"Warning: dimension of row %d inconsistent - skipped",
		  nr);
	  SCTPUT(text);
	  continue;
	}
     }
    if (0<nstr) err = TCARDD(tid, nr, nstr, 1, maxis, start);
    if (0<nstp) err = TCARDD(tid, nr, nstp, 1, maxis, step);
    if (0<nident) err = TCERDC(tid, nr, nident, ident, &inull);
     else sprintf(ident,"Table element >%s,%s,@%d<",tname,col,nr);

/*  create new image file  */

     sprintf(iname,"%s%04d",pfix,nr);
     dt = (dt_double) ? D_R8_FORMAT : D_R4_FORMAT;
     err = SCFCRE(iname, dt, F_O_MODE, F_IMA_TYPE, msize, &fid);
     iva = 1; ns = msize;
     while (0<ns) {
	n = (ns<items) ? ns : items;
	err = SCFPUT(fid, iva, n, buf);
	iva += n; ns -= n;	
      }

     err = SCDWRI(fid, "NAXIS",   &maxis, 1,     1, kunit);
     err = SCDWRI(fid, "NPIX",    npix,   1, maxis, kunit);
     err = SCDWRD(fid, "START",   start,  1, maxis, kunit);
     err = SCDWRD(fid, "STEP",    step,   1, maxis, kunit);
     err = SCDWRC(fid, "IDENT", 1, ident, 1, strlen(ident), kunit);
     err = SCDWRC(fid, "CUNIT", 1, cunit,  1, 16, kunit);
     for (n=0; n<maxis; n++)
       err = SCDWRC(fid, "CUNIT", 1, cunit,  16*(n+1), 16, kunit);
     cut[0] = cut[2] = cl; cut[1] = cut[3] = ch;
     err = SCDWRR(fid, "LHCUTS",  cut, 1,  4, kunit);
     SCFCLO(fid);

     if (1<maxis)
       sprintf(text," Frame >%s< created, npix:%5d,%5d",iname,npix[0],npix[1]);
     else
       sprintf(text," Frame >%s< created, npix:%5d",iname,npix[0]);
     SCTPUT(text);
   }

  if (rowcount == 0)
     {
     SCTPUT("no selected rows found => no image created...");
     }
  else
     {
     sprintf(text,"%d row(s) processed",rowcount);
     SCTPUT(text);
     }

  free(buf);
  TCTCLO(tid);
  SCSEPI();

return 0;
}
