/* program: image-profiles
 * purpose: process one column SDDS screen-image file into 
 *          x and y intensity files
 * L. Emery, 1994
 */
/*
 * $Log: not supported by cvs2svn $
 * Revision 1.6  2000/05/19 15:35:29  soliday
 * Removed Solaris and Linux compiler warnings.
 *
 * Revision 1.5  1998/10/02 17:30:01  borland
 * Added -v1v2preferred option, which tells the program that if Variable1 and
 * Variable2 parameters exist in the file, it should attempt to use those
 * rather than NumberOfRows and NumberOfColumns.  Also, when v1v2 mode is
 * used, the output file has a new column giving the "real" position of each
 * pixel.
 *
 * Revision 1.4  1997/09/23 14:31:40  emery
 * Corrected the interpretation of ReadTable return value.
 *
 * Revision 1.3  1997/08/28 20:57:31  emery
 * Changed the indentation.
 *
 */

#include "mdb.h"
#include "SDDS.h"
#include "scan.h"
#include "match_string.h"

#define SET_BACKGROUND 0
#define SET_RASTER 1
#define SET_VERBOSE 2
#define SET_V1V2PREFERRED 3
#define N_OPTIONS 4
char *option[N_OPTIONS] = {
  "background", "raster", "verbose", "v1v2preferred",
  };

#define HORIZONTAL 0
#define VERTICAL 1
#define N_RASTERS 2
char *raster_names[N_RASTERS] = {
  "horizontal",
  "vertical"
  };

char *USAGE  =  "imageProfile <SDDSfile> <root> [-background=<SDDSfile>] \n\
   [-raster={\"horizontal\"|\"vertical\"}] \n\
   [-v1v2preferred] [-verbose]\n\
    Calculates profiles and other parameters of an SDDS image file\n\
    and writes them in two output files <root>.[xy]\n\
    These files contain parameters Centroid and STD (standard deviation).\n\
    The default raster is horizontal, as in a TV signal.\n\
    The vertical raster may be necesssary for files derived from sddscongen output.\n\
    Use the option -v1v2preferred if the input file has Variable1Name and\n\
    Variable2Name and you want to force the program to use these instead of\n\
    NumberOfRows and NumberOfColumns.\n\
Program by Louis Emery, ANL (This is version 2, October 1998)";

void getDimensionParameters(SDDS_TABLE *SDDS_table, char *name_of_name, char **variable, 
                            char **variableUnits,
                            double *minimum, double *interval, long *number);

int main(int argc, char **argv)
{
  SDDS_TABLE inputPage, xPage, yPage, backgroundPage;
  SCANNED_ARG *scanned;
  long i, j, i_arg;
  char *input, *backgroundFile=NULL, *outputroot;
  char x_intensityFile[80], y_intensityFile[80];
  double *data;
  double *background_data=NULL;
  int32_t n_columns;
  long NumberOfRows, NumberOfColumns;
  long BNumberOfRows, BNumberOfColumns;
  long *RowNumber, *ColumnNumber;
  double *xIntensity, *yIntensity;
  char **ColumnNames, **BColumnNames=NULL;
  long subtract_background;
  long raster;    
  double xSTD, xRMS, ySTD, yRMS, xCentroid, yCentroid;
  double TotalIntensity;
  long retval;
  long verbose = 0;
  long variable1Index, variable2Index, rowNumberType, columnNumberType, v1v2Preferred;
  double dx, dy, xmin, ymin, *variable1Data=NULL, *variable2Data=NULL;
  long nx, ny;
  char *variable1, *variable1Units, *variable2, *variable2Units;
  long firstPage;
  
  SDDS_RegisterProgramName(argv[0]);
  argc  =  scanargs(&scanned, argc, argv);
  if (argc<2)
    bomb(NULL, USAGE);

  input  =  outputroot =  NULL;
  
  verbose = v1v2Preferred = 0;
  subtract_background = 0;
  raster = HORIZONTAL;
  for (i_arg = 1; i_arg<argc; i_arg++) {
    if (scanned[i_arg].arg_type == OPTION) {
      switch(match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
      case SET_BACKGROUND:
        subtract_background = 1;
        if(!(backgroundFile = scanned[i_arg].list[1]))
          bomb("Invalid background syntax", USAGE);
        break;
      case SET_RASTER:
        if(!scanned[i_arg].list[1])
          bomb("invalid raster option seen", USAGE);
        switch(raster = match_string(scanned[i_arg].list[1], raster_names, N_RASTERS, 0)){
        case HORIZONTAL:
        case VERTICAL:
          break;
        default:
          bomb("invalid raster option seen", USAGE);
        }
        break;
      case SET_VERBOSE:
        verbose = 1;
        break;
      case SET_V1V2PREFERRED:
        v1v2Preferred = 1;
        break;
      default:
        bomb("invalid option seen", USAGE);
      }
    }
    else {
      if (!input)
        input  =  scanned[i_arg].list[0];
      else if (!outputroot)
        outputroot  =  scanned[i_arg].list[0];
      else
        bomb("too many filenames", USAGE);
    }
  }
  if (!input)
    bomb("input file not seen", NULL);
  if (!outputroot)
    bomb("outputroot name not seen", NULL);

  strcat(strcpy(x_intensityFile, outputroot), ".x");;
  strcat(strcpy(y_intensityFile, outputroot), ".y");;

  if (!SDDS_InitializeInput(&inputPage, input))
    SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);

  variable1Index = variable2Index = -1;
  if (!v1v2Preferred) {
    rowNumberType = SDDS_GetNamedParameterType(&inputPage, "NumberOfRows");
    columnNumberType = SDDS_GetNamedParameterType(&inputPage, "NumberOfColumns");
    SDDS_ClearErrors();
    if (rowNumberType && columnNumberType) {
      if (!SDDS_INTEGER_TYPE(rowNumberType) || !SDDS_INTEGER_TYPE(columnNumberType)) {
        fputs("NumberOfRows and NumberOfColumns parameters are present but at least one has a non-integer type--attempting alternative processing mode\n", stderr);
        rowNumberType = columnNumberType = 0;
      }
    }
    else
      rowNumberType = columnNumberType = 0;
    if (!rowNumberType || !columnNumberType) {
      if ((variable1Index = SDDS_GetParameterIndex(&inputPage, "Variable1Name"))<0 ||
          (variable2Index = SDDS_GetParameterIndex(&inputPage, "Variable2Name"))<0 ||
          SDDS_GetParameterType(&inputPage, variable1Index)!=SDDS_STRING ||
          SDDS_GetParameterType(&inputPage, variable2Index)!=SDDS_STRING)
        SDDS_Bomb("Can't figure out how to turn column into 2D grid!\nCheck existence and type of Variable1Name and Variable2Name");
    }
  } else {
    variable1Index = SDDS_GetParameterIndex(&inputPage, "Variable1Name");
    variable2Index = SDDS_GetParameterIndex(&inputPage, "Variable2Name");
    SDDS_ClearErrors();
    if (variable1Index>=0 && variable2Index>=0) {
      if (SDDS_GetParameterType(&inputPage, variable1Index)!=SDDS_STRING ||
          SDDS_GetParameterType(&inputPage, variable2Index)!=SDDS_STRING) {
        variable1Index = variable2Index = -1;
      }
    }
    if (variable1Index<0 || variable2Index<0) {
      rowNumberType = SDDS_GetNamedParameterType(&inputPage, "NumberOfRows");
      columnNumberType = SDDS_GetNamedParameterType(&inputPage, "NumberOfColumns");
      SDDS_ClearErrors();
      if (rowNumberType && columnNumberType) {
        if (!SDDS_INTEGER_TYPE(rowNumberType) || !SDDS_INTEGER_TYPE(columnNumberType)) {
          fputs("NumberOfRows and NumberOfColumns parameters are present but at least one has a non-integer type--attempting alternative processing mode\n", stderr);
          SDDS_Bomb("Can't figure out how to turn column into 2D grid!\n");
        }
      }
    }
  }
  
  ColumnNames = (char**)SDDS_GetColumnNames(&inputPage, &n_columns);
  if(!n_columns)
    bomb("No columns found in image file.\n", NULL);

  if (subtract_background) {
    if(!SDDS_InitializeInput(&backgroundPage, backgroundFile) ||
       SDDS_CheckParameter(&backgroundPage, "NumberOfRows", NULL, SDDS_LONG, stderr) ||
       SDDS_CheckParameter(&backgroundPage, "NumberOfColumns", NULL, SDDS_LONG, stderr) )
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
    BColumnNames = (char**)SDDS_GetColumnNames(&backgroundPage, &n_columns);
    if(!n_columns)
      bomb("No columns found in background file.\n", NULL);
    if(SDDS_ReadTable(&backgroundPage)<0)
      bomb("Problem with reading the background image file table.\n", NULL);
    if(!SDDS_GetParameter(&backgroundPage, "NumberOfColumns", &BNumberOfColumns) ||
       !SDDS_GetParameter(&backgroundPage, "NumberOfRows", &BNumberOfRows) ){
      fprintf(stderr, "error: unable to read NumberOfRows or NumberOfColumns parameter"
              " in background file\n");
      SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
      exit(1);
    }
  }
  
  /* define xPage and yPage */
  if(!SDDS_InitializeOutput(&xPage, SDDS_BINARY, 0, 
                            "x intensity profile", "intensity profile", 
                            x_intensityFile) ||
     !SDDS_InitializeOutput(&yPage, SDDS_BINARY, 0, 
                            "y intensity profile", "intensity profile", 
                            y_intensityFile) )
    SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
  
  if(0>SDDS_DefineParameter(&xPage, "InputFile", NULL, NULL, 
                            "screen image file from which this file was derived", 
                            NULL, SDDS_STRING, NULL) ||
     0>SDDS_DefineParameter(&yPage, "InputFile", NULL, NULL, 
                            "screen image file from which this file was derived", 
                            NULL, SDDS_STRING, NULL) )
    SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
  
  if(subtract_background){
    if(0>SDDS_DefineParameter(&xPage, "BackgroundFile", NULL, NULL, 
                              "background screen image file from which this file was derived", 
                              NULL, SDDS_STRING, NULL) ||
       0>SDDS_DefineParameter(&yPage, "BackgroundFile", NULL, NULL, 
                              "background screen image file from which this file was derived", 
                              NULL, SDDS_STRING, NULL) )
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
  }        
  
  if(0>SDDS_DefineParameter(&xPage, "NumberOfRows", NULL, NULL, "number of rows", 
                            NULL, SDDS_LONG, NULL) ||
     0>SDDS_DefineParameter(&yPage, "NumberOfRows", NULL, NULL, "number of rows", 
                            NULL, SDDS_LONG, NULL) ||
     0>SDDS_DefineParameter(&xPage, "NumberOfColumns", NULL, NULL, "number of columns", 
                            NULL, SDDS_LONG, NULL) ||
     0>SDDS_DefineParameter(&yPage, "NumberOfColumns", NULL, NULL, "number of columns", 
                            NULL, SDDS_LONG, NULL) )
    SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
  if(0>SDDS_DefineParameter(&xPage, "Centroid", NULL, NULL, "centroid", 
                            NULL, SDDS_DOUBLE, NULL) ||
     0>SDDS_DefineParameter(&xPage, "STD", NULL, NULL, "standard deviation", 
                            NULL, SDDS_DOUBLE, NULL) || 
     0>SDDS_DefineParameter(&yPage, "Centroid", NULL, NULL, "centroid", 
                            NULL, SDDS_DOUBLE, NULL) ||
     0>SDDS_DefineParameter(&yPage, "STD", NULL, NULL, "standard deviation", 
                            NULL, SDDS_DOUBLE, NULL) )
    SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);

  if(0>SDDS_DefineColumn(&xPage, "ColumnNumber", NULL, NULL, "column number", NULL, SDDS_LONG, 0) ||
     0>SDDS_DefineColumn(&yPage, "RowNumber", NULL, NULL, "row number", NULL, SDDS_LONG, 0) ||
     0>SDDS_DefineColumn(&xPage, "xIntensity", NULL, NULL, "intensity along x direction", NULL, SDDS_DOUBLE, 0) ||
     0>SDDS_DefineColumn(&yPage, "yIntensity", NULL, NULL, "intensity along y direction", NULL, SDDS_DOUBLE, 0) )
    SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
  
  firstPage = 1;
  while( ( retval = SDDS_ReadTable(&inputPage) ) > 0 ) {
    if(verbose) 
      printf("Processing frame %ld.\n", retval);
    
    if (variable1Index>=0 && variable1Index>=0) {
      variable1 = variable2 = NULL;
      getDimensionParameters(&inputPage, "Variable1Name", 
                             &variable1, &variable1Units, 
                             &xmin, &dx, &nx);
      getDimensionParameters(&inputPage, "Variable2Name", 
                             &variable2, &variable2Units, 
                             &ymin, &dy, &ny);
      NumberOfRows = nx;
      NumberOfColumns = ny;
      if (firstPage) {
        if (0>SDDS_DefineColumn(&yPage, variable1, NULL, variable1Units, NULL,
                                NULL, SDDS_DOUBLE, 0) ||
            0>SDDS_DefineColumn(&xPage, variable2, NULL, variable2Units, NULL,
                                NULL, SDDS_DOUBLE, 0)) {
          SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
          exit(1);
        }
      }
    } else {
      if(!SDDS_GetParameter(&inputPage, "NumberOfColumns", &NumberOfColumns) ||
         !SDDS_GetParameter(&inputPage, "NumberOfRows", &NumberOfRows) ){
        fprintf(stderr, "error: unable to read NumberOfRows or NumberOfColumns parameter\n");
        SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
        exit(1);
      }
    }
    if(!NumberOfRows || !NumberOfColumns)
      bomb("Number of columns or rows is zero.\n", NULL);
    
    if (firstPage) {
      if(!SDDS_WriteLayout(&xPage) || !SDDS_WriteLayout(&yPage))
        SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
    }
    firstPage = 0;
    
    if(!SDDS_StartTable(&xPage, NumberOfColumns) ||
       !SDDS_StartTable(&yPage, NumberOfRows) )
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
    
    SDDS_SetParameters(&xPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_VALUE, 
                       "InputFile", input, NULL);
    SDDS_SetParameters(&yPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_VALUE, 
                       "InputFile", input, NULL);

    if(subtract_background){
      SDDS_SetParameters(&xPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_VALUE, 
                         "BackgroundFile", backgroundFile, NULL);
      SDDS_SetParameters(&yPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_VALUE, 
                         "BackgroundFile", backgroundFile, NULL);
      
      if(BNumberOfRows != NumberOfRows || BNumberOfColumns != NumberOfColumns)
        bomb("Image and background rasters don't match.\n", NULL);
    }
    /* takes data from first column */    
    data  =  (double*)SDDS_GetColumnInDoubles(&inputPage, ColumnNames[0]);
    if(subtract_background){
      background_data  =  (double*)SDDS_GetColumnInDoubles(&backgroundPage, BColumnNames[0]);
    }
    
    /* Do the summations */
    xIntensity  =  (double*)malloc(sizeof(double)*NumberOfColumns);
    yIntensity  =  (double*)malloc(sizeof(double)*NumberOfRows);
    RowNumber  =  (long *)malloc(sizeof(long)*NumberOfRows);
    ColumnNumber  =  (long *)malloc(sizeof(long)*NumberOfColumns);
    if (variable1Index>=0 && variable1Index>=0) {
      if (!(variable1Data = (double*)malloc(sizeof(double)*nx)) ||
          !(variable2Data = (double*)malloc(sizeof(double)*ny)))
        SDDS_Bomb("memory allocation failure");
      for (i=0; i<nx; i++) 
        variable1Data[i] = xmin + dx*i;
      for (i=0; i<ny; i++) 
        variable2Data[i] = ymin + dy*i;
    }
    
    if(raster == HORIZONTAL) { /*default raster */
      if(!subtract_background){
        for(i = 0;i<NumberOfColumns;i++) {
          xIntensity[i] = 0;
          ColumnNumber[i] = i;
          for(j = 0;j<NumberOfRows;j++) {
            xIntensity[i] +=  data[i+j*NumberOfColumns];
          }
        }
        for(j = 0;j<NumberOfRows;j++) {
          yIntensity[j] = 0;
          RowNumber[j] = j;
          for(i = 0;i<NumberOfColumns;i++) {
            yIntensity[j] +=  data[i+j*NumberOfColumns];
          }
        }
      }
      else {
        for(i = 0;i<NumberOfColumns;i++) {
          xIntensity[i] = 0;
          ColumnNumber[i] = i;
          for(j = 0;j<NumberOfRows;j++) {
            xIntensity[i] +=  data[i+j*NumberOfColumns] - background_data[i+j*NumberOfColumns];
          }
        }
        for(j = 0;j<NumberOfRows;j++) {
          yIntensity[j] = 0;
          RowNumber[j] = j;
          for(i = 0;i<NumberOfColumns;i++) {
            yIntensity[j] +=  data[i+j*NumberOfColumns] - background_data[i+j*NumberOfColumns];
          }
        }
      }
    }
    else if(raster == VERTICAL) {
      if(!subtract_background){
        for(i = 0;i<NumberOfColumns;i++) {
          xIntensity[i] = 0;
          ColumnNumber[i] = i;
          for(j = 0;j<NumberOfRows;j++) {
            xIntensity[i] +=  data[j+i*NumberOfRows];
          }
        }
        for(j = 0;j<NumberOfRows;j++) {
          yIntensity[j] = 0;
          RowNumber[j] = j;
          for(i = 0;i<NumberOfColumns;i++) {
            yIntensity[j] +=  data[j+i*NumberOfRows];
          }
        }
      }
      else {
        for(i = 0;i<NumberOfColumns;i++) {
          xIntensity[i] = 0;
          ColumnNumber[i] = i;
          for(j = 0;j<NumberOfRows;j++) {
            xIntensity[i] +=  data[j+i*NumberOfRows] - background_data[j+i*NumberOfRows];
          }
        }
        for(j = 0;j<NumberOfRows;j++) {
          yIntensity[j] = 0;
          RowNumber[j] = j;
          for(i = 0;i<NumberOfColumns;i++) {
            yIntensity[j] +=  data[j+i*NumberOfRows] - background_data[j+i*NumberOfRows];
          }
        }
      }
    }    
    xCentroid = yCentroid = xRMS = yRMS = 0;
    TotalIntensity = 0;
    for(i = 0;i<NumberOfColumns;i++) {
      TotalIntensity += xIntensity[i];
      xCentroid += i*xIntensity[i];
      xRMS += i*i*xIntensity[i];
    }
    xCentroid /= TotalIntensity;
    xSTD = sqrt(xRMS/TotalIntensity-xCentroid*xCentroid);
    xRMS = sqrt(xRMS/TotalIntensity);
    for(j = 0;j<NumberOfRows;j++) {
      yCentroid += j*yIntensity[j];
      yRMS += j*j*yIntensity[j];
    }
    yCentroid /= TotalIntensity;
    ySTD = sqrt(yRMS/TotalIntensity-yCentroid*yCentroid);
    yRMS = sqrt(yRMS/TotalIntensity);
    SDDS_SetParameters(&xPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_VALUE, 
                       "Centroid", xCentroid, "STD", xSTD, NULL);
    SDDS_SetParameters(&yPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_VALUE, 
                       "Centroid", yCentroid, "STD", ySTD, NULL);
    SDDS_SetColumn(&xPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_REFERENCE, 
                   ColumnNumber, NumberOfColumns, "ColumnNumber");
    SDDS_SetColumn(&xPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_REFERENCE, 
                   xIntensity, NumberOfColumns, "xIntensity");
    SDDS_SetColumn(&yPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_REFERENCE, 
                   RowNumber, NumberOfRows, "RowNumber");
    SDDS_SetColumn(&yPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_REFERENCE,    
                   yIntensity, NumberOfRows, "yIntensity");
    if (variable1Index>=0 && variable1Index>=0) {
      SDDS_SetColumn(&yPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_REFERENCE,
                     variable1Data, nx, variable1);
      SDDS_SetColumn(&xPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_REFERENCE,
                     variable2Data, ny, variable2);
    }
    SDDS_WriteTable(&xPage);
    SDDS_WriteTable(&yPage);
    SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
    free(xIntensity);
    free(yIntensity);
    free(RowNumber);
    free(ColumnNumber);
    free(variable1Data);
    free(variable2Data);
  }
  if(!retval)
    bomb("Problem with reading the image file table.\n", NULL);
  
  SDDS_Terminate(&inputPage);
  if(subtract_background)
    SDDS_Terminate(&backgroundPage);
  SDDS_Terminate(&xPage);
  SDDS_Terminate(&yPage);
  return(0);
}

void getDimensionParameters(SDDS_TABLE *SDDS_table, char *name_of_name, char **variable, 
                            char **variableUnits,
                            double *minimum, double *interval, long *number)
{
  static char s[SDDS_MAXLINE], message[SDDS_MAXLINE];
  long index;
  char **ptr, *units;
  double dValue;

  if (!*variable) {
    if (!name_of_name)
      bomb("improper calling of get_dimension_parameters", NULL);
    if (!(ptr=SDDS_GetParameter(SDDS_table, name_of_name, NULL))) {
      SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
      SDDS_Bomb("Unable to get dimension parameters");
    }
    *variable = *ptr;
    sprintf(s, "%sInterval", *variable);
    if ((SDDS_GetParameterIndex(SDDS_table, s))<0 ||
        !SDDS_FLOATING_TYPE(SDDS_GetNamedParameterType(SDDS_table, s))) {
      sprintf(message, "Problem with parameter %s---check existence.  Should be floating type", s);
      SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
      SDDS_Bomb(message);
    }

    sprintf(s, "%sDimension", *variable);
    if ((SDDS_GetParameterIndex(SDDS_table, s))<0 ||
        !SDDS_INTEGER_TYPE(SDDS_GetNamedParameterType(SDDS_table, s))) {
      sprintf(message, "Problem with parameter %s---check existence.  Should be integer type", s);
      SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
      SDDS_Bomb(message);
    }

    sprintf(s, "%sMinimum", *variable);
    if (((index=SDDS_GetParameterIndex(SDDS_table, s)))<0 ||
        !SDDS_FLOATING_TYPE(SDDS_GetNamedParameterType(SDDS_table, s))) {
      sprintf(message, "Problem with parameter %s---check existence.  Should be floating type", s);
      SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
      SDDS_Bomb(message);
    }
    if (SDDS_GetParameterInformation(SDDS_table, "units", &units, SDDS_GET_BY_INDEX, index)!=
        SDDS_STRING)
      SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors);
    *variableUnits = units;
  }
  
  sprintf(s, "%sMinimum", *variable);
  if (!(SDDS_GetParameterAsDouble(SDDS_table, s, minimum))) {
    fprintf(stderr, "error: problem finding/casting %s\n", s);
    SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
    exit(1);
  }
  sprintf(s, "%sInterval", *variable);
  if (!(SDDS_GetParameterAsDouble(SDDS_table, s, interval))) {
    fprintf(stderr, "error: problem finding/casting %s\n", s);
    SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
    exit(1);
  }

  sprintf(s, "%sDimension", *variable);
  if (!(SDDS_GetParameterAsDouble(SDDS_table, s, &dValue))) {
    fprintf(stderr, "error: problem finding %s or with it's type\n", s);
    SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
    exit(1);
  }
  *number = dValue;
}


