/*===========================================================================
  Copyright (C) 1993-2010 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTifer   PLOTROW
.AUTHOR      R. Warmels, R.M. van Hees IPG-ESO Garching
.KEYWORDS    Graphics, bulk data frame, one-dimensional plotting
.LANGUAGE    C
.PURPOSE     Plot or overplot a line of a FRAME
  in/output: IN_A/C/1/60  = input frame
             P2/C/72      = line number (default 1)
             P3/C/72      = first and last pixel of the line 
                            (default the whole line). 
                            This range will be taken, if manual scaling in x 
                            has been specified else the plot will be made in 
                            auto scaling mode.
             P4/R/2       = New plot:  scales in x and y 
                                        (default is auto scaling)
             P5/C/72      = New plot:  intensity interval
	     P6/C/60	  =            2ndcolor specs
		or
	     P5/C/72	  =            c=frame,@m	for color map
	     P7/C/60	  =            different label for x-axis
	     P8/C/60	  =            different label for y-axis

             P4/R/1       = Over plot: offset in pixel intensity units
             P5/I/1       =            line type
             P6/C/60      =            intensity interval
             P7/C/60      =            2ndcolor specs
		or
	     P6/C/60	  =            c=frame,@m	for color map

.COMMENTS    none
.ENVIRONment MIDAS
             #include <midas_def.h>     Prototypes for MIDAS interfaces
             #include <plot_def.h>      General symbols for Plot routines

.VERSION     1.1     09-Sep-1993   FORTRAN --> C         RvH

 100818		last modif
-----------------------------------------------------------*/

#define _POSIX_SOURCE 1

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

#include <midas_def.h>
#include <plot_def.h>


extern void getColor();

/*

*/

int main()
{
int     access, actvals, binmod, ii, imf=-1, img = -1, imfx;
int     stat, stype, ltype, unit, nval;
int     npix[PLDIM2], npixa[PLDIM2], ndum[4], sublo[PLDIM2], subhi[PLDIM2];
int     knul, naxis, nrprow, ioff, kk, krow, orig_col, thrcol, xthrcol;

float   xmin, xmax, y_off, *xdata, *ydata, area[4], image[4], xmage[4];
float   wcfram[8], cuts[4],*yydata, athr, bthr;
register float  rval;


double  start[PLDIM2], step[PLDIM2];

char    bin[8], cmnd[16], name[82], cunit[56], ident[76], buff[82];
char    refname[64], *label[4], *xpntr, *pntr;
char    xtcoltxt[12], tcoltxt[12], ocoltxt[12];
char    colspecs[24], input[82], xycoord[82], ax_labels[62];

char    coltxt[8][12];



/* initialized variables */

int   plmode = -1;                     /* plot mode taken from keyword PMODE */

char  *err_1dim  = "*** WARNING: Image row contains only one pixel!",
      *err_flat  = "*** WARNING: zero dynamic range in data at %13.8g",
      *err_range = "*** FATAL: range in x has no overlap with current graph abscissa - no plot";

static char  *axis[PLDIM2] = { "MANU", "MANU" };



/* allocate memory for different character pointers and initialise a few */

for (ii=0; ii<4; ii++) label[ii] = osmmget(81);
(void) strcpy( label[0], "Position (" );
(void) strcpy( label[1], "Pixel value (" ); 
(void) strcpy( label[2], "Image: " );
(void) strcpy( label[3], "Row: #" );

/* for multi-color option we need that */

for (ii=0; ii<8; ii++)
   sprintf(coltxt[ii],"color=%1d",ii+1);


/* start of executable code */

(void) SCSPRO("PLTROW");		/*contact with the MIDAS monitor*/
(void) SCKGETC("MID$CMND",1,12,&actvals,cmnd );
if ( *cmnd == 'P' )			/*plot mode*/
   access = 0;
else					/*overplot mode*/
   access = 1;

ii = 1;
(void) SCPSET(F_FITS_PARM,&ii);          /* don't read in ESO.xyz keywords */


/* find file name and read header information */

(void) SCKGETC("IN_A",1,80,&actvals,name);
(void) SCFOPN(name,D_R4_FORMAT,0,F_IMA_TYPE,&imf);
(void) SCDRDI(imf,"NPIX",1,PLDIM2,&actvals,npix,&unit,&knul);
if ( npix[0] == 1 ) SCTPUT( err_1dim );

/* read the descriptors */

(void) SCDRDI(imf,"NAXIS",1,1,&actvals,&naxis,&unit,&knul);
(void) SCDRDD(imf,"START",1,PLDIM2, &actvals,start,&unit,&knul);
(void) SCDRDD(imf,"STEP",1,PLDIM2, &actvals,step,&unit,&knul);
(void) SCDRDR(imf,"LHCUTS",1,4,&actvals,cuts,&unit,&knul);
(void) SCDGETC(imf,"IDENT",1,72,&actvals,ident);
(void) SCDGETC(imf,"CUNIT",1,32,&actvals,cunit);

/* Get the manual setting for the axes */

PCKRDR("XAXIS", 4, &actvals, wcfram);
PCKRDR("YAXIS", 4, &actvals, wcfram+FOR_Y);

/* line number (Y-coordinate); default line number = 1 */

image[2] = image[3] = 1;
if ( naxis > 1 )
   { 
   (void) SCKGETC("P2",1,72,&actvals,input);
   (void) strcpy(xycoord,"<,");
   (void) strcat(xycoord,input);
   stat = Convcoo(0,imf,xycoord,PLDIM2,ndum,sublo,subhi); 
   image[2] = image[3] = sublo[1] + 1;
   BOXPTW(image+2,npix[1],start[1],step[1],area+2);
   }

/* find first and last pixel along the row (X-coordinate) */

(void) SCKGETC("P3",1,72,&actvals,input);
if ( *input == 'm' || *input == 'M' )
   {
   BOXWTP(wcfram,npix[0],start[0],step[0],image);
   BOXPTW(image,npix[0],start[0],step[0],area);
   }
else
   {
   pntr = strstr(input, ",");
   (void) strcpy(xycoord,strtok(input,","));
   (void) strcat(xycoord,",@1");
   stat = Convcoo(0,imf,xycoord,naxis,ndum,sublo,subhi); 
   image[0] = sublo[0] + 1;

   (void) strcpy(xycoord,pntr+1);
   (void) strcat(xycoord,",@1");
   stat = Convcoo(0,imf,xycoord,naxis,ndum,sublo,subhi); 
   image[1] = sublo[0] + 1;

   BOXPTW(image,npix[0],start[0],step[0],area);
   }
PCKWRR("PIXEL",4,image);


/* allocate virtual memory for a single line of the frame */

nrprow = (int) fabs(image[1] - image[0]) + 1;   /*number of points in the row*/
xdata = (float *) osmmget(2*nrprow*sizeof(float));
ydata = xdata + nrprow;


/* copy the data of the row */

nval = npix[0];
if (nval < 512) nval = 512;
(void) SCFCRE("PLOTWORK",D_R4_FORMAT,F_X_MODE,F_IMA_TYPE,nval,&imfx);
(void) SCFMAP(imfx, F_X_MODE,1,nval,&actvals,&xpntr);
ii = (image[2]-1)*npix[0] + 1;
(void) SCFGET(imf,ii,npix[0],&actvals,xpntr);
xmage[0] = image[0];
xmage[1] = image[1];
xmage[2] = 1;
xmage[3] = 1;
GETBDF(xpntr,xmage,npix,start,step,xdata,ydata);
(void) SCFUNM(imfx);


/* plot mode or overplot mode */

if (access == 0)
   {				
   /* calculate frame along X-axis */
   if ( fabs( *wcfram ) < PLT_EPS && fabs( *(wcfram+1) ) < PLT_EPS )
      {
      axis[0]   = "AUTO";
      wcfram[0] = area[0];
      wcfram[1] = area[1]; 
      wcfram[2] = wcfram[3] = 0.0;
      }

   /* calculate frame along Y-axis */
   if ( fabs(*(wcfram+FOR_Y)) < PLT_EPS && fabs( *(wcfram+FOR_Y+1)) < PLT_EPS)
      { 
      axis[1] = "AUTO";
      wcfram[FOR_Y]   = cuts[0];
      wcfram[FOR_Y+1] = cuts[1];
      if ( wcfram[FOR_Y] == wcfram[FOR_Y+1] )
         MINMAX( ydata, nrprow, wcfram + FOR_Y, wcfram + FOR_Y + 1 );
      if ( wcfram[FOR_Y] == wcfram[FOR_Y+1] )
         {  
         (void) sprintf( buff, err_flat,  wcfram[FOR_Y]);
         SCTPUT( buff );
         }
      wcfram[FOR_Y+2] = wcfram[FOR_Y+3] = 0.0;
      }
      
   GETFRM(axis[0],wcfram);
   GETFRM(axis[1],wcfram + FOR_Y);
   PCKWRR("XWNDL",4,wcfram);
   PCKWRR("YWNDL",4,wcfram+FOR_Y);
   y_off = 0.0;
   }

else                                                         /* overplot mode*/
   { 
   PCKRDR("XWNDL",4,&actvals,wcfram);
   PCKRDR("YWNDL",4,&actvals,wcfram+FOR_Y);                       

   /* does overplot data  fall within plotted frame? */
   xmin = MYMIN(wcfram[0],wcfram[1]);
   xmax = MYMAX(wcfram[0],wcfram[1]);
   if ( ( MYMAX(area[0], area[1] ) < xmin ) ||
        ( MYMIN(area[0], area[1] ) > xmax ) )
      (void) SCETER( 2, err_range );
   (void) SCKRDR("INPUTR",1,1,&actvals,&y_off,&unit,&knul);
   }


/* setup graphic device according to MIDAS settings */

PCOPEN(" "," ",access,&plmode);

/* get the symbol type, line type and binmode */

PCKRDI("STYPE",1,&actvals,&stype);
PCKRDI("LTYPE",1,&actvals,&ltype);
PCKRDC("BINMOD",4,&actvals,bin);
binmod = (strncmp(bin,"ON",2) == 0) ? 1 : 0;


/* check, if multi-colour option used */

thrcol = -1;
if (access == 0)
   {						/* PLOT/ROW */
   (void) SCKGETC("P5",1,72,&actvals,input);
   (void) SCKGETC("P6",1,20,&actvals,colspecs);
   (void) SCKGETC("P7",1,60,&actvals,ax_labels);
   if (ax_labels[0] != '?')
      {
      if (ax_labels[0] == '"') 	
         {			/* get rid of enclosing double quotes */
         ax_labels[0] = ' ';
         ii = CGN_JNDEXC(ax_labels,'"');		/* get last " */
         if (ii > -1) ax_labels[ii] = '\0';	/* cut off, if " found */
         (void) strcpy( label[0], &ax_labels[1]);
         }
       else
         (void) strcpy( label[0], ax_labels);
      (void) strcat(label[0]," (" );
      }
   (void) SCKGETC("P8",1,60,&actvals,ax_labels);
   if (ax_labels[0] != '?')
      {
      if (ax_labels[0] == '"') 	
         {			/* get rid of enclosing double quotes */
         ax_labels[0] = ' ';
         ii = CGN_JNDEXC(ax_labels,'"');		/* get last " */
         if (ii > -1) ax_labels[ii] = '\0';	/* cut off, if " found */
         (void) strcpy( label[1], &ax_labels[1]);
         }
       else
         (void) strcpy( label[1], ax_labels);
      (void) strcat(label[1]," (" );
      }
   }
else
   {						/* OVERPLOT/ROW */
   (void) SCKGETC("P6",1,72,&actvals,input);
   (void) SCKGETC("P7",1,20,&actvals,colspecs);
   }

(void) SCKRDI("PLISTAT",9,1,&actvals,&orig_col,&unit,&knul);
(void) sprintf(ocoltxt,"color=%1d",orig_col);	/* save originally set color */


/* --- one color for all --- */

if (*input == '?')			/* all in one colour */
   PCDATA(stype,ltype,binmod,xdata,ydata,y_off,nrprow);


/* --- colors defined in separate data buffer --- */

else if ( ((*input == 'C') || (*input == 'c'))  &&  (input[1] == '=') )
   {				/* We use a separate colour map */
   double  ddummy;
   float   rbuf;
   int     icol, *idata, *ipntr;
   char   cdum[64];		/* parse string: low,hi(frame,@refline) */

   (void) strcpy(cdum,&input[2]);

   /* check for: frame,@row   or    @row */

   ii = CGN_INDEXC(cdum,',');
   if (ii > 0)
      {                              /* use another frame for reference */
      cdum[ii] = '\0';
      if (CGN_singleframe(cdum,1,refname) == 0)
         (void) strcpy(refname,cdum);	/* we translated image name */
      (void) SCFOPN(refname,D_I4_FORMAT,0,F_IMA_TYPE,&img);
      npixa[1] = 1;			/* in case of 1-dim frame */
      (void) SCDRDI(img,"NPIX",1,PLDIM2,&actvals,npixa,&unit,&knul);
      ii ++;
      }
   else
      {
      img = imf;                     /* use same frame */
      npixa[0] = npix[0];
      npixa[1] = npix[1];
      ii = 0;
      }

   /* now `ii' points to isolated row spec.:  < or > or @no */

   if (cdum[ii] == '<')
      kk = 1;
   else if (cdum[ii] == '>')
      kk = npixa[1];
   else if (cdum[ii] == '@')
      {
      (void) CGN_CNVT(cdum+ii+1,1,1,&kk,&rbuf,&ddummy);       /* skip `@' */
      if ((kk < 1) || (kk > npixa[1]))
         SCETER(37,"color spec. line no. out of limits ...");
      }
   else
      SCETER(36,"bad color spec. line no. ...");

   ii = (kk-1)*npixa[0] + 1;                 /* offset to that row */
   idata = (int *) osmmget(nrprow * sizeof(int));
   if (img == imf)		/* same file */
      {
      float *rpntr;

      yydata = (float *) osmmget(nrprow * sizeof(float));
      (void) SCFGET(img,ii,npix[0],&actvals,(char *)yydata);
      ipntr = idata, rpntr = yydata;
      for (kk=0; kk<ii; kk++)
         {
         *ipntr++ = (int) (*rpntr);
         rpntr++;
         }
      osmmfree(yydata);
      }
   else
      (void) SCFGET(img,ii,npix[0],&actvals,(char *)idata);

   ioff = 0;
   icol = *idata;
   AG_SSET(coltxt[icol-1]);              /* start with 1st color */

   ipntr = idata;
   for (ii=ioff; ii<nrprow; ii++)
      {
      kk = *ipntr++;
      if (kk != icol)
         {
         krow = ii - ioff;              /* nopts to plot before colour change */
         PCDATA(stype,ltype,binmod,xdata+ioff,ydata+ioff,y_off,krow+1);
         icol = kk;
         AG_SSET(coltxt[icol-1]);              /* change to next color */
         ioff = ii;
         }
      }

   krow = nrprow - ioff;
   if (krow > 0)
      PCDATA(stype,ltype,binmod,xdata+ioff,ydata+ioff,y_off,krow);

   osmmfree(idata);

   AG_SSET(ocoltxt);		/* reset to original colour */
   }


/* --- two colors used depending on pixels in/outside given interval --- */

else			
   {		 		/* We use the colour band option */
   double  ddummy;
   float   *yorig, rbuf[2];
   int     refline;
   char    cdum[64];		/* parse string: low,hi(frame,@refline) */

   yorig = (float *) 0;


   kk = CGN_INDEXC(input,'(');
   if (kk > 0) 
      { 
      refline = 1;
      ii = CGN_INDEXC(input,')');
      if (ii < kk) SCETER(36,"bad reference line no. ...");
       
      input[ii] = '\0';
      (void) strcpy(cdum,input+kk+1);	/* pull out (ref-spec) */
      input[kk] = '\0';			/* now just the intensity interval */


      /* check for: frame,@row   or    @row */

      ii = CGN_INDEXC(cdum,',');
      if (ii > 0) 
         {				/* use another frame for reference */
         cdum[ii] = '\0';
         if (CGN_singleframe(cdum,1,refname) == 0)
            (void) strcpy(refname,cdum);	/* we translated image name */
         (void) SCFOPN(refname,D_R4_FORMAT,0,F_IMA_TYPE,&img);
         (void) SCDRDI(img,"NPIX",1,PLDIM2,&actvals,npixa,&unit,&knul);
         ii ++;
         }
      else
         {
         img = imf;			/* use same frame */
         npixa[0] = npix[0];
         npixa[1] = npix[1];
         ii = 0;
         }

      /* now `ii' points to isolated row spec.:  < or > or @no */

      if (cdum[ii] == '<')
         kk = 1;		
      else if (cdum[ii] == '>')
         kk = npixa[1];
      else if (cdum[ii] == '@')
         {
         (void) CGN_CNVT(cdum+ii+1,1,1,&kk,rbuf,&ddummy);	/* skip `@' */
         if ((kk < 1) || (kk > npixa[1]))
            SCETER(37,"refline no. out of limits ...");
         }
      else
         SCETER(36,"bad reference line no. ...");

      yorig = yydata = (float *) osmmget(nrprow * sizeof(float));
      ii = (kk-1)*npixa[0] + 1;			/* offset to that row */
      
      /* read data from same or reference frame (-> img) */
      (void) SCFGET(img,ii,npix[0],&actvals,(char *)yydata);
      MINMAX(yydata,nrprow,cuts,cuts+1);

      if (img == imf)
         (void) printf("using row no. %d of same frame as reference\n",kk);
      else
         (void) printf
               ("using row no. %d of frame %s as reference\n",kk,refname);
      }

   else
      {
      refline = 0;
      cuts[0] = wcfram[FOR_Y];
      cuts[1] = wcfram[FOR_Y+1];
      yydata = ydata;		/* use intensities directly */
      }

   /* now work on: `low,high' and `incolo,outcolo' */

   kk = CGN_INDEXC(input,',');
   if (kk < 1) SCETER(34,"bad intensity interval...");

   if (*input == '<')
      (void) sprintf(cdum,"%f,",cuts[0] - 1.); 
   else
      {
      (void) strncpy(cdum,input,kk+1);			/* copy 1st number */
      cdum[kk+1] = '\0';
      }
   (void) strcpy(input,input+kk+1);

   if (*input == '>')
      {
      (void) sprintf(buff,"%f",cuts[1] + 1.); 
      (void) strcat(cdum,buff);
      }
   else
      (void) strcat(cdum, input);			/* copy 2nd number */
      
   ii = CGN_CNVT(cdum,2,2,&unit,rbuf,&ddummy);
   if (ii < 2) SCETER(35,"bad intensity interval...");
   athr = rbuf[0];			/* interval boundary */
   bthr = rbuf[1];
   
   getColor(colspecs,&thrcol,&xthrcol);		/* color name to no. */
   if (thrcol < 0) thrcol = 2;		/* default to red inside colour band */
   if (xthrcol < 0) xthrcol = 4;	/* default to blue outside colour b. */

   (void) sprintf(tcoltxt,"color=%1d",thrcol);
   (void) sprintf(xtcoltxt,"color=%1d",xthrcol);

   ioff = 0;
   AG_SSET(xtcoltxt);		/* start with `out-of' color */

  inside_color:
   for (ii=ioff; ii<nrprow; ii++)
      {
      rval = *yydata;
      if ((rval >= athr) && (rval <= bthr)) 
         {
         krow = ii - ioff;		/* nopts to plot before colour change */
         if (krow > 0) 			/* krow+1 for smoother overlap */
            PCDATA(stype,ltype,binmod,xdata+ioff,ydata+ioff,y_off,krow+1);
         AG_SSET(tcoltxt);		/* change to thrcol color */
         ioff = ii;
         goto outside_color;
         }
      yydata ++;
      }

   /* we end outside colour band - plot last data */
   krow = nrprow - ioff;		
   if (krow > 0) 
      PCDATA(stype,ltype,binmod,xdata+ioff,ydata+ioff,y_off,krow);

   goto after_plot;


  outside_color:
   for (ii=ioff; ii<nrprow; ii++)
      {
      rval = *yydata;
      if ((rval < athr) || (rval > bthr)) 
         {
         /*
         printf("switch to orig color:rval = %f, ii= %d, ioff = %d\n",
                rval,ii,ioff);
         */
         krow = ii - ioff;		/* nopts to plot after colour change */
         if (krow > 0) 			/* krow+1 for smoother overlap */
            PCDATA(stype,ltype,binmod,xdata+ioff,ydata+ioff,y_off,krow+1);
         AG_SSET(xtcoltxt);		/* change to outside color */
         ioff = ii;
         goto inside_color;
         }
      yydata ++;
      }

   /* we end inside colour band - plot last data */
   krow = nrprow - ioff;
   if (krow > 0) 
      PCDATA(stype,ltype,binmod,xdata+ioff,ydata+ioff,y_off,krow);

after_plot:
   if (refline == 1) osmmfree(yorig);
   AG_SSET(ocoltxt);		/* reset to original colour */
   }


if (plmode >= 0 && access == 0)
   { 
   if (strlen(cunit) > (size_t) 0)
      {
      (void) strncat(label[0],cunit+16,16);
      (void) strncat(label[1],cunit,16);
      }
   for (ii=0; ii<PLDIM2; ii++)
      {
      (void) strcat(label[ii],")");
      LABSTR(label[ii]);
      }

   /*  plot axes and labels */

   PCFRAM(wcfram,wcfram+FOR_Y,label[0],label[1]);

   if ( plmode == 1 )
      {
      (void) strcat (label[2],name );
      (void) sprintf(buff, "%-.0d", (int) image[2] );
      (void) strcat(label[3], buff );
      PLIDEN(plmode,label[2], label[3] );
      }
   else if ( plmode == 2 )
      PLBDFI(plmode,name,ident,image);
   }

for (ii=0; ii<4; ii++) osmmfree(label[ii]);
osmmfree(xdata);


/*  close plot file and terminate graphic operations */

PCCLOS();

return SCSEPI();
}
 
