/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.COPYRIGHT   (c)  1996-2011  European Southern Observatory
.IDENT       tbl3bdf.c
.LANGUAGE    C
.AUTHOR      K. Banse ESO - SDD/PSD
.KEYWORDS    3D-table, extract, image
.ENVIRON     MIDAS
.PURPOSE     extract a 3D-table column and store as image file

.VERSION  
 100802		created, based on tbl2bdf.c code of PJG

 111130		last modif
------------------------------------------------------------------------*/

#include   <stdlib.h>      
#include   <stdio.h>
#include   "computer.h" 	/* needed for isNULL... */
#include   "midas_def.h"	/* MIDAS definitions               */

#define    MXLEN                 62  /* Max. length of parm strings     */
#define    MXNAME                82  /* Max. length of file names       */



int main()

{
void  *buf;

char  col[MXLEN], row[MXLEN], tname[MXLEN];
char  dim[MXLEN], coor[MXLEN], ident[MXLEN], cunit[MXLEN];
char  iname[MXNAME], text[MXNAME];

int   fid, tid, ncol, nrlo, nrhi, nrows;
int   n, nr, nb, ns, iva, sf, dt_double;
int   mcol, mrow, msort, macol, marow;
int   dt, items, msize, maxis, dtcol;
int   iformat, m;
int   npix[2], kunit[4], fix, rowcount, felem;
int   *kbuf, k, kcl, kch;

float  *fbuf, f, fcl, fch, cut[4];

double *dbuf, d, cl, ch, dd[4], step[2], start[2];


/*
COPY/T3IMA  table  column  1st-row,norow  1st-el,noelem  coords-spec  image  
*/



(void) SCSPRO("TBL3BDF");  

dbuf = (double *) 0;
fbuf = (float *) 0;
kbuf = (int *) 0;
fix = 0;
ch = cl = 0.0;
fcl = fch = 0.0;

/*  get table name and open it  */

(void) SCKGETC("IN_A", 1, MXLEN-2, &iva, tname);
(void) TCTOPN(tname, F_I_MODE, &tid);
(void) TCIGET(tid, &mcol, &mrow, &msort, &macol, &marow);


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

(void) SCKGETC("INPUTC",1,MXLEN-2,&iva,col);
(void) TCCSER(tid,col,&ncol);
if (ncol < 1) SCETER(33,"invalid column entered");


/* for given column get data type (dtcol), no. of elements (items),
   nobytes needed for storage of all elements (nb) */

(void) TCBGET(tid,ncol,&dtcol,&items,&nb);


/*  get 1st row and no. of rows to copy */

nrlo = 1; nrows = 1;				/* default values */
(void) SCKGETC("ROW", 1, MXLEN-2, &iva, row);

if (row[0] == '@')			/* @row => row */
   (void) strcpy(ident,row+1);
else
   (void) strcpy(ident,row);

n = CGN_INDEXC(ident,',');
if (n < 0)				/* only start row */
   {
   m = -1;
   m = atoi(ident);
   if (m != -1)
      nrlo = m;
   else
      SCETER(7,"invalid 1st row entered");
   }
else
   {
   ident[n++] = '\0';	/* n is incremented after op... */
   if (n == 1)				/* input was: ,norows. */
      {
      ;
      }
   else					/* get 1st row */
      {
      m = -1;
      m = atoi(ident);
      if (m != -1)
         nrlo = m;
      else
         SCETER(7,"invalid 1st row entered");
      }

   if (ident[n] != '\0')		/* get no. of rows */
      {
      m = -1;
      m = atoi(ident+n);
      if (m != -1)
         nrows = m;
      else
         SCETER(8,"invalid no. of rows entered");
      }
   }

if ((nrlo < 1) || (nrlo > mrow))
   SCETER(7,"invalid 1st row entered");
if (nrows < 1) 
   SCETER(8,"invalid no. of rows entered");
if (nrows > mrow) nrows = mrow;

nrhi = nrlo + nrows - 1;		/* adjust to existing rows */
if (nrhi > mrow) nrhi = mrow;
(void) sprintf(text,"extract rows from row %d until row %d",nrlo,nrhi);
SCTPUT(text);

/*
printf("nrlo = %d, nrhi = %d, nrows = %d\n",nrlo,nrhi,nrows);
printf("iva = %d, msize = %d\n",iva,msize);
*/

/* we need to know the exact size of the result image */

rowcount = 0;
maxis = 1;

for (nr=nrlo; nr<=nrhi; nr++)
   {
   (void) TCSGET(tid,nr,&sf);		/* check if row is selected */
   if (!sf) 
      {
      sprintf(text,"row %d not selected - skipped",nr);
      SCTPUT(text);
      }
   else
      rowcount++;
   }
if (rowcount < 1)
   SCETER(22,"no row extracted - no result image...");

    
if (rowcount > 1) 			/* we'll create a 2-dim image */
   maxis = 2;


/* log column, row where image was extracted from in descr IDENT */
(void) sprintf(ident,"from col. %s (row %d) of table %s",col,nrlo,tname);


/*  get size of x-axis of image: 1st_el,noelem */

felem = 1;				/* defaults */
msize = items; 
(void) SCKGETC("DIM",1,MXLEN-2,&iva,dim);

if (dim[0] != '*') 
   {
   nr = CGN_CNVT(dim,1,2,kunit,cut,&d);
   if (nr < 1)
      SCETER(3, "invalid element specs entered");

   felem = kunit[0];		/* always use first as the 1st pixel no. */

   if ((felem < 1) || (felem > items))
      SCETER(3, "invalid 1st element entered");

   if (nr > 1) msize = kunit[1];	/* also noelem entered */
   if (msize < 1) 
      SCETER(3, "invalid no. of elements entered");
   }

iva = items - felem + 1;		/* resulting no. of elems to read */
if (msize > iva) msize = iva; 		/* adjust (truncate) size */
npix[0] = msize;
npix[1] = rowcount;


/*  get coordinates for image  */

start[0] = start[1] = 0.0;	/* default values */
step[0] = step[1] = 1.0;

(void) SCKGETC("COOR", 1, MXLEN-2, &iva, coor);
if (coor[0] != '*') 
   {
   nr = CGN_CNVT(coor,4,4,kunit,cut,dd);
   if (nr < 2)
      SCETER(4, "invalid/insufficient xstart,xstep values entered");

   start[0] = dd[0];		/* update for x-coord. */
   step[0] = dd[1];

   if (npix[1] > 1) 
      {
      if (nr < 4)
         SCTPUT("missing y-coords entered - defaults for y-axis used...");
      else
         {
         start[1] = dd[2];	/* also values for y-axis entered */
         step[1] = dd[3];
         }
      }
   }


/*  get image name and create result image */

(void) SCKGETC("OUT_A",1,MXNAME-2,&iva,iname);

if (dtcol == D_R8_FORMAT)		/* check column data type */
   {
   nb = msize * DD_SIZE;
   }
else if (dtcol == D_R8_FORMAT)
   {
   nb = msize * RR_SIZE;
   }
else 					/* for size of I1, I2 see below */
   {
   nb = msize * II_SIZE;
   }

buf = calloc((size_t)nb, 1);
if (!buf) 
   SCETER(5,"cannot allocate buffer for result image");

iformat = dtcol;
if (dtcol == D_R8_FORMAT)
   dbuf = (double *) buf; 
else if (dtcol == D_R4_FORMAT)
   fbuf = (float *) buf;
else
   {				/* I1, I2, I4 -> all goto I4 format */
   kbuf = (int *) buf;
   iformat = D_I4_FORMAT;
   }

ns = npix[0] * npix[1];
(void) SCFCRE(iname,iformat,F_O_MODE,F_IMA_TYPE,ns,&fid);


/*  go through specified range of rows    */

iva = 1;				/* start of buffer */

for (nr=nrlo; nr<=nrhi; nr++) 
   {
   (void) TCSGET(tid, nr, &sf);		/* check if row is selected */
   if (!sf) 
      {					/* skip not selected rows */
      continue;
      }


   /*  read 3D-table element   */

   if (dtcol == D_R8_FORMAT)
      {	
      (void) TCARDD(tid,nr,ncol,felem,msize,dbuf);
      cl = ch = dbuf[0];
      if (isNULLDOUBLE(cl))		 /* check 1st elem for Null */  
         {
         (void) sprintf(text,"Warning: 1st element of row %d = Null ...",nr);
         SCTPUT(text);
         }
      else
         {
         for (n=0; n<msize; n++) 
            {
            d = dbuf[n];
	    if (d<cl) cl = d; else if (ch<d) ch = d;
	   }
         }
      }
   else if (dtcol == D_R4_FORMAT)
      {	
      (void) TCARDR(tid, nr, ncol, felem, msize, fbuf);
      fcl = fch = fbuf[0];
      if (isNULLFLOAT(fcl))		/* check 1st elem for Null */ 
         {
         (void) sprintf(text,"Warning: 1st element of row %d = Null ...",nr);
         SCTPUT(text);
         }
      else
         {
         for (n=0; n<items; n++) 
            {
	    f = fbuf[n];
	    if (f<fcl) fcl = f; else if (fch<f) fch = f;
	    }
         }
      }
   else 
      {	
      (void) TCARDI(tid, nr, ncol, felem, msize, kbuf);
      kcl = kch = kbuf[0];
      if (isNULLINT(kcl))		/* check 1st elem for Null */ 
         {
         (void) sprintf(text,"Warning: 1st element of row %d = Null ...",nr);
         SCTPUT(text);
         }
      else
         {
         for (n=0; n<items; n++) 
            {
	    k = kbuf[n];
	    if (k<kcl) kcl = k; else if (kch<k) kch = k;
	    }
         }
      }

   /* fill next row of image */
   (void) SCFPUT(fid,iva,msize,buf);
   iva += msize;
   }

if (dtcol == D_R8_FORMAT)
   {
   cut[0] = cut[2] = (float) cl; cut[1] = cut[3] = (float) ch;
   }
else if (dtcol == D_R4_FORMAT)
   {
   cut[0] = cut[2] = fcl; cut[1] = cut[3] = fch;
   }
else
   {
   cut[0] = cut[2] = (float) kcl; cut[1] = cut[3] = (float) kch;
   }

free(buf);


/* fill necessary info for output image */

(void) SCDWRI(fid,"NAXIS", &maxis, 1, 1, kunit);
(void) SCDWRI(fid,"NPIX",  npix, 1, maxis, kunit);
(void) SCDWRD(fid,"START", start,1, maxis, kunit);
(void) SCDWRD(fid,"STEP",  step,1, maxis, kunit);
(void) SCDWRC(fid,"IDENT", 1, ident, 1, strlen(ident), kunit);
(void) strcpy(cunit,"                ");	/* 16 blanks for data unit */
(void) strcat(cunit,"                ");	/* for x-axis */
(void) strcat(cunit,"                ");	/* for y-axis */
iva = (maxis + 1) * 16;
(void) SCDWRC(fid,"CUNIT",1,cunit,1,iva,kunit);
(void) SCDWRR(fid,"LHCUTS",cut,1,4,kunit);

/* append keyword HISTORY to descr. HISTORY of image */
(void) SCKGETC("HISTORY",1, 80, &iva, text);
(void) SCDWRC(fid,"HISTORY",1,text,-1,80,&iva);

(void) SCFCLO(fid);

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


(void) TCTCLO(tid);
(void) SCSEPI();

return 0;
}
