/**---------------------------------------------------------------------------
 ** 
 ** db.c -- Access CTD data from a CODAS database
 ** 
 ** Author          : Pierre Jaccard
 ** Created On      : 1999/07/15 16:47:03
 ** Last Modified By: Pierre Jaccard
 ** Last Modified On: 1999/07/16 20:06:36
 ** Update Count    : 2
 ** Directory       : /home/pego/pcd1/codas3c/gfi/src/libs/ctd/
 ** Version         : 0.0
 ** Status          : Unknown
 ** ---------------------------------------------------------------------- ** 
 ** DESCRIPTION: 
 ** 
 **    These functions are used to access various CTD data from a CODAS
 **    database.
 ** 
 ** ---------------------------------------------------------------------- ** 
 ** REVISIONS: 
 ** ---------------------------------------------------------------------- ** 
 ** CHANGES: 
 **------------------------------------------------------------------------**/

#include "db.h"

/* ------------------------------------------------------------------
	 This function gets a profile of CTD data from current database pointer. It
	 is an exact copy of the function get_ctd_profile used by adcpsect.
	 ------------------------------------------------------------------ */

#if PROTOTYPE_ALLOWED
void get_ctd_prf(/* Place for CTD data */
                 CTD_PROFILE_TYPE *prof)
#else
void get_ctd_prf(prof)
CTD_PROFILE_TYPE *prof;
#endif
{
   double sigma;           /* dummy used in SVAN */
   double theta;
   int step = 1;
   int ngaps = 0;     /* max number of interpolations done */
   int ierr;
   int n, ng;
   int i;

   get_latlon(&(prof->position));
   check_dbget(TIME, (char *) &(prof->time), sizeof(prof->time),
                                       "DBGET, time");

   prof->n = (int) check_dbget_f(P, prof->pressure, NPMAX, "DBGET_F, pressure");

   n = (int) check_dbget_f(TEMPERATURE, prof->temperature, NPMAX,
                                       "DBGET_F, temperature");
   prof->n = min_val(prof->n, n);

   n = (int) check_dbget_f(SALINITY, prof->salinity, NPMAX,
                                       "DBGET_F, salinity");
   prof->n = min_val(prof->n, n);

   /* It is assumed that the CTD data are nearly perfect, so this
      gap filling will only occasionally be called into play, and
      only for small gaps.
   */
   ng = fill_gaps(prof->salinity, prof->n);
   ngaps = ng;
   ng = fill_gaps(prof->temperature, prof->n);
   ngaps = max_val(ngaps, ng);
   ng = fill_gaps(prof->pressure, prof->n);
   ngaps = max_val(ngaps, ng);
   if (ngaps == prof->n)
      prof->n = 0;  /* don't try to use this profile */

   for (i=0; i < prof->n; i++)
   {
      prof->depth[i] = (float) p_depth( prof->pressure[i], prof->position.lat);
      prof->svel[i]  = (float) SVEL( prof->salinity[i], prof->temperature[i],
                              prof->pressure[i]);
      switch (prof->density_var)
      {
         case CTD_SVAN:
            prof->sigma_sva[i]  = (float) SVAN( prof->salinity[i], 
																								prof->temperature[i],
																								prof->pressure[i], &sigma);
            break;
         case CTD_SIGMA_THETA:
            theta = THETA(prof->salinity[i], prof->temperature[i],
                          0.0, prof->pressure[i]);
            (void) SVAN( prof->salinity[i], theta, 0.0, &sigma);
            prof->sigma_sva[i] = (float) sigma;
            break;
         case CTD_POT_SVAN:
            theta = THETA(prof->salinity[i], prof->temperature[i],
                          0.0, prof->pressure[i]);
            prof->sigma_sva[i] = (float) SVAN( prof->salinity[i], 
																							 theta, 0.0, &sigma);
                        break;
         case CTD_SIGMA_T:
            (void) SVAN( prof->salinity[i], prof->temperature[i], 0.0, &sigma);
            prof->sigma_sva[i]  = (float) sigma;
		        break;
         case CTD_NONE:
            prof->sigma_sva[i] = BADFLOAT;
                        break;
         default:
            printf("\n%d is an invalid density variable specification\n",
                    prof->density_var);
            exit(-1);
      }

   }
   if (prof->n == 0)   /* try the next one */
   {
      printf("\nBad CTD profile.");
      write_ymdhms_time(stdout, &(prof->time));
      printf("  position: %f  %f\n", prof->position.lat,
                                       prof->position.lon);
      DBMOVE(&step, &ierr);
      check_error(ierr, "DBMOVE in get_ctd_prf");
      get_ctd_prf(prof);      /* recursive call */
   }
   return;  /* only exit */
}                       /* get_ctd_profile */


/* ------------------------------------------------------------------
	 Given a depth in meters, this function returns the interpolated temperature
	 at this depth. Interpolation method used is linear interpolation. 

   RETURNS: BADFLOAT on error.
	 ------------------------------------------------------------------ */

#if PROTOTYPE_ALLOWED
FLOAT get_ctd_temp(/* Pointer to CTD data */
                   CTD_PROFILE_TYPE *ctd, 
                   /* Interpolation depth */
                   FLOAT depth)
#else
FLOAT get_ctd_temp(ctd, depth)
#endif
{

	float p1, p2, t1, t2;
	int i, done;
	
	/* Parses the data in the CTD array */
	i = done = 0;
	while(!done){
		/* Loop exit flag */
		done = !((ctd->pressure[i] < depth) 
						&& (ctd->temperature[i] < ADJ_BADFLOAT) && (i<(ctd->n)));
		/* Keep previous good data */
		if((ctd->temperature[i] < ADJ_BADFLOAT) && !done){
			t1 = ctd->temperature[i];
			p1 = ctd->pressure[i];
		}
		i++;
	}
	i--;

	if(error_found(i==0, "Specified depth too shallow"))
		return(BADFLOAT);
	if(error_found(i==NPMAX, 
								 "No temperature for specified depth"))
		return(BADFLOAT);
	p2 = ctd->pressure[i];
	t2 = ctd->temperature[i];
	
	return((FLOAT) t1 + (t2-t1)*(depth-p1)/(p2-p1));

}

/* ------------------------------------------------------------------
	 Given a depth in meters, this function returns the interpolated salinity
	 at this depth. Interpolation method used is linear interpolation. 

   RETURNS: BADFLOAT on error.
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
FLOAT get_ctd_sal(/* Pointer to CTD data */
                  CTD_PROFILE_TYPE *ctd, 
                  /* Interpolation depth */
                  FLOAT depth)
#else
FLOAT get_ctd_sal(ctd, depth)
#endif
{

	float p1, p2, s1, s2;
	int i, done;
	
	/* Parses the data in the CTD array */
	i = done = 0;
	while(!done){
		/* Loop exit flag */
		done = !((ctd->pressure[i] < depth) 
						&& (ctd->salinity[i] < ADJ_BADFLOAT) && (i<(ctd->n)));
		/* Keep previous good data */
		if((ctd->salinity[i] < ADJ_BADFLOAT) && !done){
			s1 = ctd->salinity[i];
			p1 = ctd->pressure[i];
		}
		i++;
	}
	i--;

	if(error_found(i==0, "Specified depth too shallow"))
		return(BADFLOAT);
	if(error_found(i==NPMAX, 
								 "No salinity for specified depth"))
		return(BADFLOAT);
	p2 = ctd->pressure[i];
	s2 = ctd->salinity[i];
	
	return((FLOAT) s1 + (s2-s1)*(depth-p1)/(p2-p1));

}


