Removing more backup files
authorSteele <gsteele@tudelft.net@tud12721.fritz.box>
Mon, 5 Aug 2013 19:00:05 +0000 (21:00 +0200)
committerSteele <gsteele@tudelft.net@tud12721.fritz.box>
Mon, 5 Aug 2013 19:00:05 +0000 (21:00 +0200)
spyview/ImageData.C.~1.114.~ [deleted file]
spyview/ImageData.H.~1.56.~ [deleted file]
spyview/ImagePrinter.C.~1.104.~ [deleted file]
spyview/ImageWindow.C.~1.295.~ [deleted file]
spyview/bisector.H.~1.3.~ [deleted file]
spyview/spypal_import.C.~1.6.~ [deleted file]
spyview/spyview.C.~1.272.~ [deleted file]
spyview/static_link_notes.txt~ [deleted file]
spyview/update_exe.sh~ [deleted file]
spyview/update_webpage.sh~ [deleted file]

diff --git a/spyview/ImageData.C.~1.114.~ b/spyview/ImageData.C.~1.114.~
deleted file mode 100644 (file)
index bf42c8b..0000000
+++ /dev/null
@@ -1,3367 +0,0 @@
-#include <assert.h>
-#include "ImageData.H"
-#include "string.h"
-#include <Fl/filename.H>
-#include <stdlib.h>
-#include <FL/Fl.H>
-#include <time.h>
-#include "misc.h"
-#include "mypam.h"
-#include "../config.h"
-
-#include <algorithm>
-// From http://www.redhat.com/docs/manuals/enterprise/RHEL-3-Manual/gcc/variadic-macros.html
-
-#define badfile(A, ...) {info(A, ## __VA_ARGS__); return -1;}
-#define badfilec(A, ...) {fclose(fp); info(A, ## __VA_ARGS__); return -1;} // ALso close the file.
-
-#define LINESIZE 1024*1024
-
-#define MTX_HEADER_SIZE 256*10
-
-// mingw32 does not seem to implement NAN properly: it seems to be set to 0.
-#ifdef WIN32
-#define NAN INFINITY
-#define isnan(A) isinf(A)
-#endif
-
-//some handy local functions
-
-double parse_reading(char *line, int col);
-double nextreading(FILE *fp, int col, int &lnum);
-int nextline(FILE *fp, char *buf);
-
-ImageData::ImageData()
-{
-  data_loaded = 0;
-  orig_data = NULL;
-  qmin = xmin = ymin = 0;
-  qmax = xmax = ymax = 1;
-  auto_quant = 1;
-  auto_quant_percent = 50.0;
-  incorrect_column = COPY_ADJACENT;
-  mtx_cut_type = XY;
-  mtx_index = 0;
-  do_mtx_cut_title = false;
-  data3d = false;
-  gpload_type = COLUMNS;
-  gp_column = 2;
-  datfile_type = MATRIX;
-  fallbackfile_type = PGM;
-}
-
-ImageData::~ImageData()
-{
-  clear();
-}
-
-void ImageData::clear()
-{
-  if (orig_data != NULL) //was using "data_loaded", but we had a big memory leak...
-    {
-      //info("clearing image data arrays\n");
-      delete [] orig_data;
-      delete [] raw_data;
-      delete [] quant_data;
-      delete [] threshold_reject;
-      orig_data = NULL;
-    }
-  data_loaded = 0;
-}
-
-void ImageData::reallocate()
-{
-  clear();
-  orig_data = new double[width*height];
-  raw_data = new double[width*height];
-  quant_data = new int[width*height];
-  threshold_reject = new bool[width*height];
-  data_loaded = 1;
-}
-
-void ImageData::resize_tmp_arrays(int new_width, int new_height)
-{
-  // Only ever make things bigger
-  if (new_width*new_height > orig_width*orig_height)
-    {
-      delete [] quant_data;
-      delete [] threshold_reject;
-      quant_data = new int[new_width*new_height];
-      threshold_reject = new bool[new_width*new_height];
-    }
-}
-
-void ImageData::reset()
-{
-  memcpy(raw_data, orig_data, sizeof(double)*orig_width*orig_height);
-  width = orig_width;
-  height = orig_height;
-  xmin = orig_xmin;
-  ymin = orig_ymin;
-  xmax = orig_xmax;
-  ymax = orig_ymax;
-  xname = orig_xname;
-  yname = orig_yname;
-}
-
-void ImageData::saveMTX(const char *filename)
-{
-  FILE *fp = fopen(filename, "wb");
-  if (fp == NULL)
-    {
-      info("error opening file %s", filename);
-      return;
-    }
-
-  fprintf(fp, "Units, %s,"
-         "%s, %e, %e,"
-         "%s, %e, %e," 
-         "Nothing, 0, 1\n",
-         zname.c_str(), 
-         xname.c_str(), xmin, xmax,
-         yname.c_str(), ymax, ymin); 
-  fprintf(fp, "%d %d 1 8\n", width, height);
-
-  for (int i=0; i<width; i++)
-    for (int j=0; j<height; j++) 
-      fwrite(&raw(i,j), sizeof(double), 1, fp);
-  fclose(fp);
-}
-
-void ImageData::shift_data(int after_row, int offset)
-{
-  double *new_row = new double[width];   // less efficient, but easier to read the code
-  for (int j=0; j<height; j++)
-    {
-      if (j>=after_row)
-       {
-         for (int i=0; i<width; i++)
-           {
-             int i2 = i - offset; 
-             if (i2 > width-1) i2 = i2 % (width);
-             if (i2 < 0) i2 = i2 + (-i2/width+1)*width;
-             if (i2>=0 && i2 < width) 
-               new_row[i] = raw(i2,j);
-             else
-               new_row[i] = -1e2; // we should never get here if we
-                                  // did the bounds checking right
-           }
-         for (int i=0; i<width; i++)
-           raw(i,j) = new_row[i];
-       }
-    }
-  delete [] new_row;
-}
-
-void ImageData::rescale_data(double new_qmin, double new_qmax)
-{
-  for (int i = 0; i<width*height; i++)
-    raw_data[i] = new_qmin + (raw_data[i]-qmin)/(qmax-qmin)*(new_qmax-new_qmin);
-  qmax = new_qmax;
-  qmin = new_qmin;
-}
-
-void ImageData::store_orig()
-{
-  memcpy(orig_data, raw_data, sizeof(double)*width*height);
-  orig_width = width;
-  orig_height = height;
-  orig_xmin = xmin;
-  orig_ymin = ymin;
-  orig_xmax = xmax;
-  orig_ymax = ymax;
-  orig_xname = xname;
-  orig_yname = yname;
-}
-
-void ImageData::load_int(int *data, 
-                        int w, int h,
-                        double x1, double x2,
-                        double y1, double y2,
-                        double z1, double z2)
-{
-  xmin = isnan(x1) ? x1 : 0;
-  xmax = isnan(x2) ? x2 : width-1;
-  ymin = isnan(y1) ? y1 : 0;
-  ymax = isnan(y2) ? y2 : height-1;
-  qmin = isnan(z1) ? z1 : 0;
-  qmax = isnan(z2) ? z2 : QUANT_MAX;
-  width = w;
-  height = h;
-
-  reallocate();
-  xname = "X";
-  yname = "Y";
-  zname = "Data";
-  
-  // Perform conversion to floating point at very first step, even if
-  // the data is integer: we will then requantize it by calling
-  // quantize().
-
-  // We may want to have a UI option to preserve orginal quantization:
-  // turning off auto_quant should work... (although it will always be
-  // preserved anyway in the raw_data, and so also in the line cuts)
-
-  for (int i=0; i<width*height; i++)
-    raw_data[i] = qmin + 1.0*data[i]*(qmax-qmin)/QUANT_MAX;
-  
-  store_orig();
-}
-
-void ImageData::load_raw(double *data, 
-                        int w, int h,
-                        double x1, double x2, 
-                        double y1, double y2)
-{
-  xmin = isnan(x1) ? x1 : 0;
-  xmax = isnan(x2) ? x2 : width-1;
-  ymin = isnan(y1) ? y1 : 0;
-  ymax = isnan(y2) ? y2 : height-1;
-  width = w;
-  height = h;
-
-  reallocate();
-  
-  xname = "X";
-  yname = "Y";
-  zname = "Data";
-
-  memcpy(raw_data, data, width*height*sizeof(double));
-  store_orig();
-}
-
-int ImageData::load_file(const char *name)
-{
-  // We will identify the relevant helper function by the filename
-  // extension
-
-  const char *ext = strrchr(name, '.');
-
-  data_loaded = 0;
-  if (ext == NULL)
-    badfile("Unsupported extension on file: %s\n", name);
-      
-  if (strcmp(ext, ".Stm") == 0)
-    return load_STM(name);
-  else if (strcmp(ext, ".pgm") == 0)
-    return load_PGM(name);
-  else if (strcmp(ext, ".mtx") == 0)
-    return load_MTX(name);
-  else if (strcmp(ext, ".dat") == 0)
-    {
-      if (datfile_type == MATRIX)
-       return load_DAT(name);
-      else if (datfile_type == GNUPLOT)
-       return load_GP(name);
-      else if (datfile_type == DELFT_LEGACY)
-       return load_Delft(name);
-      else if (datfile_type == DAT_META)
-       return load_DAT_meta(name);
-    }
-  else if (strcasecmp(ext, ".TIF") == 0)
-    return load_XL30S_TIF(name);
-  else 
-    {
-      if (fallbackfile_type == PGM)
-       return load_PGM(name);
-      else if (fallbackfile_type == MTX)
-       return load_MTX(name);
-      else //if (fallbackfile_type == DAT)
-       {
-         if (datfile_type == MATRIX)
-           return load_DAT(name);
-         else if (datfile_type == GNUPLOT)
-           return load_GP(name);
-         else if (datfile_type == DELFT_LEGACY)
-           return load_Delft(name);
-         else if (datfile_type == DAT_META)
-           return load_DAT_meta(name);
-       }
-    }
-}
-
-int ImageData::load_STM(const char *name)
-{
-  // variables for binary read
-  int m = 0;
-  unsigned char tmp[2];
-  short unsigned int datatmp;
-
-  // variables for header info
-  int w, h;
-  double xvrange, yvrange, xcal, ycal;    
-  int chnum;
-  char buf1[256], buf2[256];
-  char ch_name[256];
-  char ch_units[256];
-  double ch_scale;
-
-  // Some Stm headers (older ones, v2.5.1 software, at least), have 0x800 byte headers.
-  // Version 2.6.0 also have 0x800 byte headers.
-  // The newer ones, v 2.6.3, have 0x1000 byte headers.
-  // Any space not used by the header info is filled with 0x2e up until the last byte
-  // before the image data starts, which is always 0x00.
-
-  char header[0x1000];
-  int hdrlen;
-
-  FILE *fp = fopen(name, "rb");
-  if(fp == NULL)
-    badfile("Unable to open file \"%s\": %s\n",name,strerror(errno));
-
-  // Read the second line of the file, which has the software version
-  int s1, s2, s3;
-  if (fgets(buf1, 256, fp) == NULL)
-    badfilec("Short file error\n");
-  if (fgets(buf1, 256, fp) == NULL)
-    badfilec("Short file error\n");
-  if (sscanf(buf1, "SwV %d.%d.%d", &s1, &s2, &s3) != 3)
-      hdrlen = 0x800;
-  else 
-    {
-      if ((s2 > 5) && (s3 > 2))
-       hdrlen = 0x1000;
-      else
-       hdrlen = 0x800;
-    }
-  
-  // Rewind and now read the correct header length
-  rewind(fp);
-  assert(hdrlen > 0);
-  if (fread(header, 1, hdrlen, fp) < static_cast<unsigned>(hdrlen))
-    badfilec("Invalid STM file");
-       
-  if (sscanf(strstr(header, "Pix"), "Pix %d", &w) != 1)
-    badfilec("Invalid width\n");
-
-  if (sscanf(strstr(header, "Lin"), "Lin %d", &h) != 1)
-    badfilec("Invalid height\n");
-
-  if (sscanf(strstr(header, "SR0"), "SR0 %lf", &xvrange) != 1)  // range in volts
-    badfilec("Invalid xrange\n");
-
-  if (sscanf(strstr(header, "SR1"), "SR1 %lf", &yvrange) != 1)
-    badfilec("Invalid yrange\n");
-  
-  if (sscanf(strstr(header, "S00"), "S00 %lf", &xcal) != 1) // scanner calibration in Ang/V
-    badfilec("Invalid xscale\n");
-
-  if (sscanf(strstr(header, "S10"), "S10 %lf", &ycal) != 1)
-    badfilec("Invalid xscale\n");
-
-  if (sscanf(strstr(header, "ImC"), "ImC %d", &chnum) != 1)
-    badfilec("Invalid chnum\n");
-
-  sprintf(buf1, "A%dN", chnum);
-  sprintf(buf2, "A%dN %%256\[^\n]", chnum);
-  if (sscanf(strstr(header, buf1), buf2, ch_name) != 1)
-    badfilec("Invalid channel name\n");
-
-  sprintf(buf1, "A%dU", chnum);
-  sprintf(buf2, "A%dU %%256[^\n]", chnum);
-  if (sscanf(strstr(header, buf1), buf2, ch_units) != 1)
-    badfilec("Invalid channel units\n");
-
-  sprintf(buf1, "A%dV", chnum);
-  sprintf(buf2, "A%dV %%lf\n", chnum);
-  if (sscanf(strstr(header, buf1), buf2, &ch_scale) != 1)
-    badfilec("Invalid channel scale\n");
-
-
-  // Now update the ranges and stuff
-  
-  xmin = 0;
-  xmax = xvrange * xcal / 10000; // in microns
-  xname = "Microns";
-
-  ymin = 0;
-  ymax = yvrange * ycal / 10000; // in microns
-  yname = "Microns";
-  
-  // Let's leave the STM file Z scale just as 0 to 65535
-  // (It's usually just the +/- 10V anyway, which is not any more physical...)
-
-  zname = "DAC Value";
-
-  width = w; height = h;
-  
-  reallocate();
-
-  for (int i=0; i<width*height; i++)
-    {
-      m=fread(&tmp[1], 1, 1, fp); // byteswap from the SGI
-      m=fread(&tmp[0], 1, 1, fp);
-      if (m == 0)
-       badfilec( "Read error row %d!\n", i/w);
-      memcpy(&datatmp, &tmp, 2); 
-      datatmp = datatmp + 32768; // overflow the short unsigned int to convert from 16-bit signed to 16-bit unsigned
-      raw_data[i] = datatmp;
-
-      if (raw_data[i] > 65535 || raw_data[i] < 0)
-       {
-         warn("%4d %4d Data %02x %02x %.1f %6d\n", i/w, i%w, tmp[0], tmp[1], raw_data[i], datatmp);
-         //getchar();
-       }
-    }
-  fclose(fp);
-  store_orig();
-  data3d = false;
-  return 0;
-}
-
-
-int ImageData::load_PGM(const char *name) 
-{ 
-  char buf[1024];
-  char *p;
-
-  char xunit[256];
-  char yunit[256];
-  char zunit[256];
-
-  int maxval;
-
-  //FILE *fp = fopen(name, "rb");
-  // This is very annoying! pgm_readpgm exits on error...
-  // I will have to write a more fault tolerant routine myself.
-  //gray **image;
-  //gray maxval;
-  //image = pgm_readpgm(fp, &width, &height, &maxval);
-  //reallocate();
-  //fclose(fp);
-
-  FILE *fp = fopen(name, "rb");
-  if(fp == NULL)
-    badfile("Unable to open file \"%s\": %s\n",name,strerror(errno));
-
-  qmin = 0;
-  qmax = 65535;
-  xmin = 0;
-  xmax = width-1;
-  ymin = 0;
-  ymax = height-1;
-
-  sprintf(xunit, "Pixels");
-  sprintf(yunit, "Pixels");
-  sprintf(zunit, "Gray Value");
-
-  // Get the first two lines: I always put comments below the image size 
-  if (fgets(buf,sizeof(buf),fp) == NULL)
-    badfilec("no characters read: empty or short file?");
-  if (strncmp(buf, "P5", 2) != 0)
-    badfilec("wrong magic number %s: only raw pgm files are supported", buf);
-  if (fgets(buf,sizeof(buf),fp) == NULL)
-    badfilec("no characters read: empty or short file?");
-  while (buf[0] == '#') // ignore any non-spyview comments
-    fgets(buf,sizeof(buf),fp);
-  if (sscanf(buf, "%d %d", &width, &height) != 2)
-    badfilec("error reading width and height from line %s", buf);
-
-  // Allocate the arrays now that we have the width and height
-  reallocate();
-  
-  // Now get any lines that contain comments
-  while (true)
-    {
-      fgets(buf, 1024, fp);
-      if (buf[0] != '#')
-       break;
-      p = &buf[1];
-      while (*p == ' ') p++;
-      if (parse_pgm_comments("zmin", "%lf", &qmin, p, name)) continue;
-      if (parse_pgm_comments("zmax", "%lf", &qmax, p, name)) continue;
-      if (parse_pgm_comments("xmin", "%lf", &xmin, p, name)) continue;
-      if (parse_pgm_comments("xmax", "%lf", &xmax, p, name)) continue;
-      if (parse_pgm_comments("ymin", "%lf", &ymin, p, name)) continue;
-      if (parse_pgm_comments("ymax", "%lf", &ymax, p, name)) continue;
-      if (parse_pgm_comments("xunit", "%s", xunit, p, name)) continue;
-      if (parse_pgm_comments("yunit", "%s", yunit, p, name)) continue;
-      if (parse_pgm_comments("zunit", "%s", zunit, p, name)) continue;
-    }
-  xname = xunit;
-  yname = yunit;
-  zname = zunit;
-
-  // The next item is the maxval, which should already be in the
-  // buffer: we need to know if the data is one byte or two.
-  if (sscanf(buf, "%d", &maxval) != 1) 
-    badfilec("error reading maxval");
-  
-  unsigned char b1;
-  unsigned char b2;
-  int data;
-  // Now lets read the data
-  for (int i=0; i<width*height; i++)
-    {
-      if (fread(&b1, 1, 1, fp) != 1)
-       badfilec("short file at pixel %d", i);
-      if (maxval > 255)
-       {
-         if (fread(&b2, 1, 1, fp) != 1)
-           badfilec("short file at pixel %d", i);
-         data = b1*256+b2;
-       }
-      else 
-       data = b1;
-      raw_data[i] =  qmin + 1.0*data*(qmax-qmin)/QUANT_MAX;
-    }
-
-  store_orig();
-  fclose(fp);
-  data3d = false;
-  return 0;
-}
-
-int ImageData::parse_pgm_comments(const char *ident, const char *fmt, void *val, char *p, const char *filename)
-{
-  if (strncmp(p, ident, 3) == 0)
-    {
-      p = strchr(p, ' ');
-      if (strcmp(fmt, "%s") == 0) 
-       { 
-         char *cval = (char *)val;
-         while (*p == ' ') p++;
-         strcpy(cval, p); 
-         for(int i = strlen(cval)-1; i > 0 && isspace(cval[i]); i--)
-           cval[i] = 0; // get rid of blank spaces at the end
-         return 1; 
-       }
-      if (sscanf(p, fmt, val) != 1)
-       badfile( "Invalid %s %s in file %s\n", ident, p, filename);
-      return(1);
-    }
-  return(0);
-}
-  
-int ImageData::load_MTX(const char *name)
-{
-  if (mtx.load_file(name) == -1) return -1;
-  load_mtx_cut();
-  data3d = true;
-  return 0;
-}
-
-int ImageData::load_GP(const char *name)
-{
-  if (gpload_type == COLUMNS)
-    {
-      if (mtx.load_gp_cols(name) == -1) return -1;
-      // Good default settings for gp_cols
-      mtx_index = gp_column;
-      mtx_cut_type = 0;
-      do_mtx_cut_title = false;
-    }
-  if (gpload_type == INDEX)
-    {
-      if (mtx.load_gp_index(name, gp_column) == -1) return -1;
-      //mtx_index = 0;
-      //mtx_cut_type = 2;
-      do_mtx_cut_title = true;
-    }
-  
-  load_mtx_cut();
-  data3d = true;
-  return 0;
-}
-
-int ImageData::load_DAT_meta(const char *name)
-{
-  int n = mtx.load_dat_meta(name, gp_column);
-  if (n == -1)
-    {
-      warn("Error reading metadata file\n");
-      return -1;
-    }
-  else if (n == -2)
-    {
-      warn("Error reading data file\n");
-      return -1;
-    }
-  // Why would I set these?
-  //mtx_index = 0;
-  //mtx_cut_type = 2;  // Range checking should be done in load_mtx_cut(), which it is.
-  load_mtx_cut();
-  data3d = true;
-  return 0;
-}
-    
-
-void ImageData::load_mtx_cut()
-{
-  if (!mtx.data_loaded)
-    error("load_mtx_cut called with no mtx data loaded!");
-
-  mtx_cut_type = static_cast<mtxcut_t>(mtx_cut_type % 3); //in case the user set it to an integer instead of using the enums
-
-  //info("loading mtx cut type %d (YZ = 0, XY = 1, XZ = 2)\n", mtx_cut_type);
-
-  if (mtx_index<0) mtx_index = 0;
-  if (mtx_index > mtx.size[mtx_cut_type]-1) mtx_index = mtx.size[mtx_cut_type]-1;
-  
-  int xaxis = (mtx_cut_type+1)%3;
-  int yaxis = (mtx_cut_type+2)%3;
-  int zaxis = (mtx_cut_type)%3;
-
-  width = mtx.size[xaxis];
-  height = mtx.size[yaxis];
-
-  //info("xaxis is %d width %d\n", xaxis, width);
-  //info("yaxis is %d height %d\n", yaxis, height);
-
-  reallocate();
-
-  //warn( "mtx_cut_type = %d, xaxis = %d, yaxis = %d\n", mtx_cut_type, xaxis, yaxis);
-  //warn( "width %d height %d\n", width, height);
-  //warn( "loading index %d type %d\n", mtx_index, mtx_cut_type);
-
-  for (int i=0; i<width; i++)
-    for (int j=0; j<height; j++)
-      {
-       if (mtx_cut_type == 0)
-         raw(i,j) = mtx.getData(mtx_index, i, j);
-       else if (mtx_cut_type == 1)
-         raw(i,j) = mtx.getData(j, mtx_index, i);
-       else 
-         raw(i,j) = mtx.getData(i, j, mtx_index);
-      }
-
-  xname = mtx.axisname[xaxis];
-  yname = mtx.axisname[yaxis];
-  
-  if (do_mtx_cut_title)
-    {
-      char buf[256];
-      snprintf(buf,256,"%g", mtx.get_coordinate(zaxis,mtx_index));
-      zname = mtx.dataname + " at " + mtx.axisname[zaxis] + " = " + buf;
-    }
-  else
-    zname = mtx.dataname;
-  
-  // This is the proper way to do it:
-
-  xmin = mtx.get_coordinate(xaxis, 0);
-  xmax = mtx.get_coordinate(xaxis, width-1);
-  
-  // Y is always flipped
-  ymin = mtx.get_coordinate(yaxis, height-1);
-  ymax = mtx.get_coordinate(yaxis, 0);
-  
-  store_orig();
-}
-
-int ImageData::load_Delft(const char *name)
-{
-  vector<double> data;
-  char linebuffer[LINESIZE];
-  FILE *fp = fopen(name, "rb");
-  if(fp == NULL)
-    badfile("Unable to open file \"%s\": %s\n",name,strerror(errno));
-  int nread = 0;
-  int num_points = 0;
-  int points_per_sweep = -1;
-  int num_sweeps = -1;
-  double sweep_min = NAN;
-  double sweep_max = NAN;
-  bool found_sweep_max = false;
-  double last_sweep;
-  double last_data;
-  string first_sweep_header;
-  string last_sweep_header;
-  string second_sweep_header;
-
-  // This file format is a pain in the ass.  In particular since there
-  // are so many variations of it. I find the whole thing unbelievably
-  // retarded.
-  //
-  // The basic structure something like this:
-  //
-  // 0 XL GATE VOLTAGE (mV)
-  // 0 YL CURRENT (pA),  Y2L CURRENT (pA)
-  // 0 T T.U. Delft, TCS & Magnet PMS & dewar gnd disconnected, still heater from battery ,6-10-2008, 13:12
-  // -1 L B=0.000T T=19.9mK sw=DAC6 D1=5.00 D2=0.00 D3=-1000.00 D4=0.00 D5=0.00 D6=-1000.00 D7=0.00 D8=0.00
-  // [sweep data...]
-  // 0 XL GATE VOLTAGE (mV)
-  // 0 YL CURRENT (pA),  Y2L CURRENT (pA)
-  // 0 T T.U. Delft, TCS & Magnet PMS & dewar gnd disconnected, still heater from battery ,6-10-2008, 13:14
-  // -2 L B=0.000T T=19.9mK sw=DAC6 D1=5.00 D2=0.00 D3=-998.00 D4=0.00 D5=0.00 D6=600.00 D7=0.00 D8=0.00
-  // [sweep data...]
-  //
-  // Parsing is as follows:
-  //   
-  //   - look for "0 XL" to indicate new sweep
-  //   - sweep value is from col 2
-  //   - data value is from following columns
-
-  if (mtx.progress_gui)
-    mtx.open_progress_gui();
-
-  while (1)
-    {
-      nread++;
-      if (fgets(linebuffer, LINESIZE, fp) == NULL)
-       break;
-
-      if (nread % 100 == 0) 
-       {
-         static char buf[256];
-         snprintf(buf, sizeof(buf), "Lines read: %d", nread);
-         if (mtx.progress_gui)
-           {
-             mtx.msg->value(buf);
-             Fl::check();
-           }
-       }
-
-      if (strstr(linebuffer, "0 XL") != NULL)
-       {
-         //info("found sweep, line %d", nread);getchar();
-         if (num_sweeps == -1) // this is the XL line at top of file
-           {
-             if (fgets(linebuffer, LINESIZE, fp) == NULL) break;
-             if (fgets(linebuffer, LINESIZE, fp) == NULL) break;
-             if (fgets(linebuffer, LINESIZE, fp) == NULL) break;
-             nread += 3;
-             first_sweep_header = linebuffer;
-             num_sweeps = 0;
-             continue;
-           }
-         else
-           {
-             // if (isnan(sweep_max)) doesn't seem to work under win32?
-             if (!found_sweep_max)
-               {
-                 sweep_max = last_sweep;
-                 found_sweep_max = true;
-                 info("settings sweep max to %e from line %d\n", sweep_max, nread+4-1);
-               }
-             num_sweeps++;
-             if (points_per_sweep == -1)
-               points_per_sweep = num_points;
-             else if (num_points != points_per_sweep)
-               badfilec("%d points in sweep %d doesn't match previous value %d\nline number %d\n", 
-                        num_points, num_sweeps, points_per_sweep, nread);
-             num_points = 0;
-             
-             if (fgets(linebuffer, LINESIZE, fp) == NULL) break;
-             if (fgets(linebuffer, LINESIZE, fp) == NULL) break;
-             if (fgets(linebuffer, LINESIZE, fp) == NULL) break;
-             nread+=3;
-             last_sweep_header = linebuffer;
-
-             if (num_sweeps == 1)
-               second_sweep_header = last_sweep_header;
-
-             continue;
-           }
-         
-       }
-      
-      if (strchr("#\n\r",linebuffer[0]) != NULL)
-       continue;
-
-      //if (sscanf(linebuffer, "%*f\t%lf\t%lf", &last_sweep, &last_data) != 2)
-      last_data = parse_reading(linebuffer, gp_column);
-      if (isnan(last_data)) 
-       {
-         //info("line\n%s\ncgp_column %d\nval %e\n", linebuffer, gp_column, last_data);
-         badfilec("invalid data in delft file at line %d\nline: %s\n", nread, linebuffer);
-       }
-
-      data.push_back(last_data);
-      if (num_points == 0) sweep_min = last_sweep;
-      num_points++;
-    }
-  
-  if (mtx.progress_gui)
-    mtx.close_progress_gui();
-
-  num_sweeps++;
-  if (num_points != points_per_sweep)
-    {
-      info("Incomplete last sweep: \n"
-          "%d points in sweep %d doesn't match previous value %d\n", 
-          num_points, num_sweeps, points_per_sweep);
-      num_sweeps--;
-    }
-      
-
-  info("points_per_sweep %d num_sweeps %d\n", points_per_sweep, num_sweeps);
-
-  unsigned int i,j;
-  i = first_sweep_header.find("sw=", 0);
-  j = first_sweep_header.find("D1", i);
-
-  string sweepname = first_sweep_header.substr(i+3,j-i-4);
-  
-  info("i %d j %d sweepname set to _%s_", i, j, sweepname.c_str());
-  
-  info("\n\n%s%s%s\n", 
-       first_sweep_header.c_str(), 
-       second_sweep_header.c_str(), 
-       last_sweep_header.c_str());
-
-  height = points_per_sweep;
-  width = num_sweeps;
-  reallocate();
-
-  info("data " _STF " w*h %d\n", data.size(), width*height);
-  
-  //for (int i=0; i<width*height; i++)
-  //raw_data[i] = data[i];
-
-  for (int i=0; i<width; i++)
-    for (int j=0; j<height; j++)
-      raw(i,j) = data[i*height+(height-1-j)];
-  
-  data3d = false;
-  ymin = sweep_min;
-  ymax = sweep_max;
-  xmin = 0; 
-  xmax = num_sweeps;
-  xname = "Loop Variable";
-  yname = sweepname;
-  zname = "Current (pA)";
-  store_orig();
-
-  fclose(fp);
-  return 0;
-}  
-  
-
-// copied from fei2pgm test code
-
-int fei_error(char *msg, const char *name)
-{
-  warn(msg, name);
-  return -1;
-}
-
-int ImageData::load_XL30S_TIF(const char *name)
-{
-  char buf[0x1200];
-  double mag;
-  char *p;
-
-  int size = 712*484; // we support only low res tifs for now
-
-  // First get the header
-
-  FILE *fp = fopen(name, "r");
-
-  fread(buf, 1, 0x1200, fp);
-
-  // Read the magnification
-
-  for (int i=0; i<0x1200; i++)
-    if ( (p = strstr(buf+i, "Magni")) != 0)
-      break;
-  if (p == NULL) 
-    return fei_error("error: could not find magnification tag in XL30S TIF file %s", name);
-
-  if (sscanf(p, "Magnification = %lf", &mag) == 0)
-    return fei_error("error: could not read magnification in XL30S TIF file %s", name);
-
-  info("XL30S TIF Mag is %g\n", mag);
-
-  // Check for XLFileType tag to see if this is really an XL30s TIF
-  p = NULL;
-  for (int i=0; i<0x1200; i++)
-    if ( (p = strstr(buf+i, "XLFileType")) != 0)
-      break;
-  if (p == NULL)
-    return fei_error("file %s does not seem to be and XL30s TIFF", name);
-
-  // Try to seek to start of the data (always last chunk of file?)
-
-  if (fseek(fp, -size, SEEK_END) == -1)
-    return fei_error("Error seeking in file: %s", name);
-  
-  xname = "Microns";
-  yname = "Microns";
-  zname = "SEM Signal";
-  xmin = 0; ymin = 0;
-  xmax = 712.0/215.0/mag*29736.822;
-  ymax = 484.0/215.0/mag*29736.822;
-  width = 712;
-  height = 484;
-  reallocate();
-  
-  unsigned char tmp[size];
-  fread(tmp, 1, size, fp);
-  fclose(fp);
-  
-  for (int i=0; i<size; i++)
-    raw_data[i] = tmp[i];
-
-  store_orig();
-  data3d = false; 
-  return 0;
-}
-  
-// Copied from dat2pgm
-int ImageData::load_DAT(const char *name)
-{
-  int w, col;
-  int h, row;
-  
-  vector<double> data;
-
-  char linebuffer[LINESIZE];
-  char *p;
-
-  double datatmp;
-
-  char sep[] = " \t\n\r";
-
-  FILE *fp = fopen(name, "rb");
-  if(fp == NULL)
-    badfile("Unable to open file \"%s\": %s\n",name,strerror(errno));
-
-  row = col = w = h = 0;
-  
-  while (1)
-    {
-      if (fgets(linebuffer, LINESIZE, fp) == NULL)
-       break;
-   
-      // Figure out what kind of line this is
-      for(p = linebuffer; *p != 0 && isspace(*p); p++)
-       ;
-
-      if(*p == '\n' || *p == 0 || *p == '#')
-       continue;
-
-      col = 0;
-      p = strtok(linebuffer, sep);
-      while (p != NULL)
-       {
-         if (sscanf(p, "%lf", &datatmp) != 1)
-           warn( "load_DAT: invalid data at row %d col %d: \"%s\", copying last read value\n", row, col, p);
-         data.push_back(datatmp);
-         col++;
-         p = strtok(0, sep);
-       }
-
-      if (row == 0)
-       w = col;
-      else if (w != col)
-       {
-         if (col == 0)
-           break;      // ignore empty lines at the end.
-         if(col < w) // This row is too short
-           {
-             warn( "number of columns %d at row %d does not match width of previous rows (%d)\n", col, row, w);
-             double d = 0; // This is used for ZERO; Mean updates the value so they can share insertion code.   
-             switch(incorrect_column)
-               {
-               case EXIT:            
-                 exit(-1);
-               case COPY_ADJACENT:
-                 d = data[data.size()];
-                 for (int i=0; i < (w-col); i++)
-                   data.push_back(d);
-                 break;
-               case DROP:
-                 data.erase(data.begin()+(row*w),data.end());
-                 row--;
-                 break;
-               case FILL_MEAN:
-                 for(int i = 0; i < col; i++)
-                   d += data[row*w + i];
-                 d = d / col;
-               case FILL_ZERO: // Warning! Falling case!
-                 assert(col < w);
-                 for(int i = 0; i < (w-col); i++)
-                   data.push_back(d);
-                 break;
-               default:
-                 badfilec( "Invalid setting for incorrect_column width: %c\n",incorrect_column);
-               }
-           }
-         else // This row is too long
-           {
-             switch(incorrect_column)
-               {
-               case EXIT:            
-                 badfilec( "number of columns %d at row %d does not match width of previous rows (%d)\n", col, row, w);
-               case COPY_ADJACENT:
-               case FILL_ZERO: // Warning! Falling case!
-               case FILL_MEAN:
-                 warn( "number of columns %d at row %d does not match; fill_mean and fill_zero no ready yet for this case.\n",col,row);
-                 warn( "dropping column.");
-                 while(col > w)
-                   {
-                     data.pop_back();
-                     col--;
-                   }
-                 break;
-               case DROP:
-                 data.erase(data.begin(),data.begin()+(row*w));
-                 row = 0;
-                 w = col;
-                 break;
-               default:
-                 badfilec( "Invalid argument for -i: %c\n",incorrect_column);
-               }
-             
-           }
-         
-       }
-      row++;
-      assert((int)data.size() == row * w);
-    }
-  h = row;
-
-  fclose(fp);
-
-  width = w; 
-  height = h;
-  reallocate();
-
-  for (int i=0; i<width*height; i++)
-    raw_data[i] = data[i];
-
-  data3d = false;
-  store_orig();
-  return 0;
-}
-
-void ImageData::find_raw_limits()
-{
-  rawmin = INFINITY; 
-  rawmax = -INFINITY;
-  
-  for (int i=0; i<width*height; i++)
-    {
-      if (raw_data[i] < rawmin) rawmin = raw_data[i];
-      if (raw_data[i] > rawmax) rawmax = raw_data[i];
-    }
-}
-
-void ImageData::quantize()
-{
-  if (auto_quant)
-    {
-      find_raw_limits();
-      qmin = (rawmin+rawmax)/2 - (rawmax-rawmin)/2/auto_quant_percent*100;
-      qmax = (rawmin+rawmax)/2 + (rawmax-rawmin)/2/auto_quant_percent*100;
-    }
-
-  for (int i=0; i<width*height; i++)
-    quant_data[i] = raw_to_quant(raw_data[i]);
-}
-
-void ImageData::log10(bool do_offset, double new_offset)
-{
-  // Refresh the rawmin and rawmax variables
-  if (do_offset) find_raw_limits();
-  
-  if (do_offset)
-    for (int i=0; i<width*height; i++)
-      raw_data[i] = log(raw_data[i]-rawmin+new_offset)/log(10.0);
-  else
-    for (int i=0; i<width*height; i++)
-      raw_data[i] = log(raw_data[i])/log(10.0);
-}
-
-void ImageData::magnitude()
-{
-  for (int i=0; i<width*height; i++)
-    raw_data[i] = fabs(raw_data[i]);
-}
-void ImageData::neg()
-{
-  for (int i=0; i<width*height; i++)
-    raw_data[i] = -raw_data[i];
-}
-void ImageData::offset(double offset, bool do_auto)
-{
-  if (do_auto) find_raw_limits();
-
-  for (int i=0; i<width*height; i++)
-    raw_data[i] = raw_data[i]+offset-(do_auto ? rawmin : 0);
-
-}
-
-void ImageData::scale(double factor)
-{ 
-  for (int i=0; i<width*height; i++)
-    raw_data[i] = raw_data[i]*factor;
-}
-
-void ImageData::gamma(double gamma, double epsilon)
-{ 
-  // This is tricky: what to do if we have a negative power and we get zero?
-  // To handle this nicely, we should add an epsilon.
-  double v1,v2;
-  for (int i=0; i<width*height; i++)
-    {
-      v1 = raw_data[i];
-      // problems with 1/0
-      if (fabs(v1) < fabs(epsilon) && gamma<0)
-       {
-         if (v1<0) v1 = -fabs(epsilon);
-         else if (v1>0) v1 = fabs(epsilon);
-         else v1 = fabs(epsilon);
-       }
-      v2 = pow(v1, gamma);
-      //if (!isfinite(v2))
-      //info("v1 %e v2 %e eps %e\n", v1, v2, epsilon);
-      if (isnan(v2))
-       raw_data[i] = 0;
-      else
-       raw_data[i] = v2;
-       
-    }
-}
-
-// calculate a 2D histogram of the dataset
-// For each x-value, tranform the y axis of the dataset into a histogram of the measured datavalues
-
-void ImageData::hist2d(double dmin, double dmax, int num_bins)
-{
-  int new_height = num_bins;
-  int histogram[new_height];  
-  double tmp;
-  int i,j;
-
-  // never shrink the arrays (leads to segfaults somewhere...)
-  double *new_data;
-  if (width * new_height > orig_width*orig_height) 
-    new_data = new double[width*new_height];
-  else
-    new_data = new double[orig_width*orig_height];
-
-  for (i=0; i<width; i++)
-    {
-        for (j=0; j<new_height; j++)
-         histogram[j] = 0;
-       for (j=0; j<height; j++)
-         {
-           tmp = (raw(i,j)-dmin)/(dmax-dmin)*new_height;
-           if (tmp >= 0 && tmp < new_height)
-             histogram[(int)tmp]++;
-         }
-       for (j=0; j<new_height; j++)
-         new_data[j*width+i] = histogram[new_height-1-j];
-    }
-  ymin = dmin;
-  ymax = dmax;
-
-  delete [] raw_data;
-  raw_data = new_data;
-  resize_tmp_arrays(width, new_height);
-  height = new_height;
-}
-
-void ImageData::interpolate(int new_width, int new_height, int type)
-{
-  if (new_width == width && new_height == height)
-    return;
-
-  // Had some trouble with segfaults. It's safest to just only make
-  // matrices bigger if needed (don't shrink ones).
-  double *new_data;
-  if (new_width * new_height > orig_width*orig_height) 
-    new_data = new double[new_width*new_height];
-  else
-    new_data = new double[orig_width*orig_height];
-
-  double x_step = (double)width/(double)new_width;
-  double y_step = (double)height/(double)new_height;
-
-  for (int j=0; j<new_height; j++)
-    for (int i = 0; i<new_width; i++)
-      new_data[j*new_width+i] = raw_interp(i*x_step,j*y_step);
-  
-  delete [] raw_data;
-  raw_data = new_data;
-
-  resize_tmp_arrays(new_width, new_height);
-
-  width = new_width;
-  height = new_height;
-}
-
-void ImageData::calculate_thresholds(int type, 
-                                    double low, double high, 
-                                    double bottom_limit, double top_limit)
-{
-  // Only data points that lie within {min,max} will be counted,
-  // others will be rejected.
-  
-  double min, max;
-
-  // type = 0 = image percentiles
-  // type = 1 = line percentiles, with optional limits
-  // type = 2 = column percentiles, with optional limits
-  // type = 3 = manual value thresholding
-
-  // Easy one: a single threshold for the whole image
-  if (type == 0 || type == 3)
-    {
-      if (type == 0) 
-       find_image_threasholds(low, high, min, max);
-      else if (type == 3)
-       {
-         min = low; max = high;
-         if (min > max) min = max;
-       }
-      for (int i=0; i<width*height; i++)
-       {
-         if (raw_data[i] > min && raw_data[i] < max)
-           threshold_reject[i] = 0;
-         else 
-           threshold_reject[i] = 1;
-       }
-    }
-  
-  // The more difficult ones: thresholds based on percentages for a
-  // given row or column
-
-  else if (type == 1)
-    {
-      vector <double> line_data;
-      for (int j=0; j<height; j++)
-       {
-         line_data.clear();
-         for (int i=0; i<width; i++)
-           if (raw(i,j) > bottom_limit && raw(i,j) < top_limit)
-             line_data.push_back(raw(i,j));
-         find_threasholds(line_data, low, high, min, max);
-         for (int i=0; i<width; i++)
-           {
-             if(raw(i,j) > min && raw(i,j) < max)
-               threshold_reject[j*width+i] = 0;
-             else
-               threshold_reject[j*width+i] = 1;
-           }
-       }
-    }
-  else //if (type == 2)
-    {
-      vector <double> col_data;
-      for (int i=0; i<width; i++)
-       {
-         col_data.clear();
-         for (int j=0; j<height; j++)
-           if (raw(i,j) > bottom_limit && raw(i,j) < top_limit)
-             col_data.push_back(raw(i,j));
-         find_threasholds(col_data, low, high, min, max);
-         for (int j=0; j<height; j++)
-           {
-             if(raw(i,j) > min && raw(i,j) < max)
-               threshold_reject[j*width+i] = 0;
-             else
-               threshold_reject[j*width+i] = 1;
-           }
-       }
-    }
-}
-  
-// A handy simple way to calculate threasholds for things like line
-// cuts. Note that you have to put the data first into an STL
-// container. It is more expensive, though.
-
-void ImageData::find_threasholds(vector <double> data, 
-                               double bottom_percent, double top_percent,
-                               double &low, double &high)
-{
-  if (bottom_percent < 0) bottom_percent = 0;
-  if (bottom_percent > 100) bottom_percent = 100;
-
-  if (top_percent < 0) top_percent = 0;
-  if (top_percent > 100) top_percent = 100;
-
-  sort(data.begin(), data.end());
-  int low_index = (int) (data.size()*bottom_percent/100.0);
-  int high_index = (int) (data.size()*(100-top_percent)/100.0-1);
-  low = data[low_index];
-  high = data[high_index];
-}
-
-// A function which calculates threasholds for the whole image using
-// the same truncation method we use to calculate the histogram, which
-// should be faster than putting the whole dataset in an stl container
-// and sorting it.
-
-void ImageData::find_image_threasholds(double bottom_percent, double top_percent,
-                                     double &low, double &high)
-{
-  int levels = 1000;
-  int histogram[levels];
-
-  double tmp;
-  int i;
-  int lowint, highint;
-  int count;
-
-  find_raw_limits();
-
-  if (bottom_percent < 0) bottom_percent = 0;
-  if (bottom_percent > 100) bottom_percent = 100;
-
-  if (top_percent < 0) top_percent = 0;
-  if (top_percent > 100) top_percent = 100;
-
-  for (i=0; i<levels; i++)
-    histogram[i] = 0;
-
-  for (i=0; i<width*height; i++)
-    {
-      tmp = (raw_data[i]-rawmin)/(rawmax-rawmin)*levels;
-      if (tmp < 0 || tmp > levels)
-       {
-         info("tmp is %g \n", tmp);
-       }
-      histogram[(int)tmp]++;
-    }
-
-  count = 0;
-  for (lowint=0; lowint<levels; lowint++)
-    {
-      count += histogram[lowint];
-      if (count > bottom_percent/100.0*width*height) break;
-    }
-  low = rawmin + lowint*(rawmax-rawmin)/levels;
-
-  count = 0;
-  for (highint=levels-1; highint>=0; highint--)
-    {
-      count += histogram[highint];
-      if (count > top_percent/100.0*width*height) break;
-    }
-  high = rawmin + highint*(rawmax-rawmin)/levels;
-
-  info("image threashold: min %e max %e\n", low, high);
-}
-
-void ImageData::remove_lines(int start, int nlines)
-{
-  for (int y = start; y < height - nlines; y++)
-    memcpy(raw_data+y*width, raw_data+(y+nlines)*width, sizeof(double)*width);
-  double new_ymin = getY(height-nlines); 
-  height = height-nlines;
-  ymin = new_ymin;
-}
-
-void ImageData::lbl(double bp, double tp, 
-                   bool whole_image_threashold, bool percentiles, 
-                   double bottom_limit, double top_limit)
-{
-  double line_average;
-  int navg;
-  
-  int type;
-
-  if (percentiles & whole_image_threashold)
-    type = 0;
-  else if (percentiles)
-    type = 1;
-  else //if (!percentiles)
-    type = 3;
-  
-  calculate_thresholds(type, bp, tp, bottom_limit, top_limit);
-  double offset;
-  
-  for (int j=0; j<height; j++)
-    {
-      line_average = navg = 0;
-      for (int i=0; i<width; i++)
-       if (!threshold_reject[j*width+i])
-         {
-           line_average += raw(i,j);
-           navg++; 
-         }
-      if (navg != 0)
-       {
-         line_average /= navg;
-         offset = line_average;
-       }
-      for (int i=0; i<width; i++)
-       raw(i,j) -= offset;
-    }
-}
-
-void ImageData::cbc(double bp, double tp, 
-                   bool whole_image_threashold, bool percentiles, 
-                   double bottom_limit, double top_limit)
-{
-  double col_average;
-  int navg;
-
-  int type;
-
-  if (percentiles & whole_image_threashold)
-    type = 0;
-  else if (percentiles)
-    type = 2;
-  else //if (!percentiles)
-    type = 3;
-  
-  calculate_thresholds(type, bp, tp, bottom_limit, top_limit);
-
-  for (int i=0; i<width; i++)
-    {
-      col_average = navg = 0;
-      for (int j=0; j<height; j++)
-       if (!threshold_reject[j*width+i])
-         {
-           col_average += raw(i,j);
-           navg++; 
-         }
-      if (navg != 0) col_average /= navg;
-
-      for (int j=0; j<height; j++)
-       raw(i,j) -= col_average;
-    }
-}
-
-void ImageData::outlier_line(bool horizontal, int pos)
-{
-  int cnt=0; // Number of lines averaged
-  if(horizontal)
-    {
-      if(pos > height || pos < 0)
-       return;
-      for(int i = 0; i < width; i++)
-       raw(i,pos)=0;
-      if(pos-1 >= 0)
-       {
-         for(int i = 0; i < width; i++)
-           raw(i,pos)=raw(i,pos)+raw(i,pos-1);
-         cnt++;
-       }
-      if(pos+1 < height)
-       {
-         for(int i = 0; i < width; i++)
-           raw(i,pos)=raw(i,pos)+raw(i,pos+1);
-         cnt++;
-       }
-      if(cnt > 1)
-       for(int i = 0; i < width; i++)
-         raw(i,pos) = raw(i,pos)/cnt;
-    }
-  else
-    {
-      if(pos > width || pos < 0)
-       return;
-      for(int i = 0; i < height; i++)
-       raw(pos,i)=0;
-      if(pos-1 >= 0)
-       {
-         cnt++;
-         for(int i = 0; i < height; i++)
-           raw(pos,i)=raw(pos,i)+raw(pos-1,i);
-       }
-      if(pos+1 < width)
-       {
-         cnt++;
-         for(int i = 0; i < height; i++)
-           raw(pos,i)=raw(pos,i)+raw(pos+1,i);
-       }
-      if(cnt > 1)
-       for(int i = 0; i < height; i++)
-         raw(pos,i) = raw(pos,i)/cnt;
-    }
-}
-void ImageData::sub_linecut(bool horizontal, int pos)
-{
-  if(horizontal)
-    {
-      if(pos >= height || pos < 0)
-       return;
-      for(int j = 0; j < height; j++)
-       for(int i = 0; i < width; i++)
-         if (j != pos) raw(i,j) -= raw(i,pos);
-      for(int i = 0; i < width; i++)
-       raw(i,pos) = 0;
-    }
-  else
-    {
-      if(pos >= width || pos < 0)
-       return;
-      for(int i = 0; i < width; i++)
-       for(int j = 0; j < height; j++)
-         if (i != pos) raw(i,j) -= raw(pos,j);
-      for(int j = 0; j < height; j++)
-       raw(pos, j) = 0;
-    }
-}
-
-void ImageData::norm_lbl()
-{
-  double min, max;
-  for (int j=0; j<height; j++)
-    {
-      min = INFINITY;
-      max = -INFINITY;
-      for (int i=0; i<width; i++)
-       {
-         if (raw(i,j) < min) min = raw(i,j);
-         if (raw(i,j) > max) max = raw(i,j);
-       }
-      for (int i=0; i<width; i++)
-       raw(i,j) = (min != max) ? (raw(i,j) - min)/(max-min) : 0;
-    }
-}
-
-void ImageData::norm_cbc()
-{
-  double min, max;
-
-  for (int i=0; i<width; i++)
-    {
-      min = INFINITY;
-      max = -INFINITY;
-      for (int j=0; j<height; j++)
-       {
-         if (raw(i,j) < min) min = raw(i,j);
-         if (raw(i,j) > max) max = raw(i,j);
-       }
-      for (int j=0; j<height; j++)
-       raw(i,j) = (min != max) ? (raw(i,j) - min)/(max-min) : 0;
-    }
-}
-
-void ImageData::fitplane(double bp, double tp, bool percentiles)
-{
-  // Formula for the plane: Z = a*X + b*Y + c
-  double a,b,c;
-  // calculate the moments
-  int N = 0;
-  double Zavg = 0;
-  double Xavg = 0;
-  double Yavg = 0;
-  double sXZ = 0;
-  double sYZ = 0;
-  double sXX = 0;
-  double sYY = 0;
-  double val;
-
-  double low, high;
-  // In principle, we should call calculate_thresholds to be
-  // consistent, but this is faster...
-  if (percentiles)
-    find_image_threasholds(bp, tp, low, high);
-  else
-    {
-      low = bp; 
-      high = tp;
-    }
-  
-  for (int x=0; x < width; x++)
-    {
-      for (int y=0; y < height; y++)
-       {
-         val = raw(x,y);
-         if (val > low && val < high)
-           {
-             Zavg += (double) val;
-             Xavg += (double) (x-width/2);
-             Yavg += (double) (y-height/2);
-             sXZ += (double) val * (x-width/2);
-             sYZ += (double) val * (y-height/2);
-             sXX += (double) (x-width/2)*(x-width/2);
-             sYY += (double) (y-height/2)*(y-height/2);
-             N++;
-           }
-       }
-    } 
-
-  Xavg /= N;
-  Yavg /= N;
-  Zavg /= N;
-
-  a = (sXZ - N*Xavg*Zavg)/(sXX - N*Xavg*Xavg);
-  b = (sYZ - N*Yavg*Zavg)/(sYY - N*Yavg*Yavg);
-  c = Zavg - a*Xavg - b*Yavg;
-  
-  for (int x=0; x<width; x++)
-    for (int y=0; y<height; y++)
-      raw(x,y) -=  a * (x-width/2) + b*(y-height/2) + c;
-
-  //warn( "a,b,c %e %e %e\n", a, b, c);
-}
-
-void ImageData::plane(double b, double a)
-{
-  for (int x=0; x<width; x++)
-    for (int y=0; y<height; y++)
-      raw(x,y) -=  a * (x-width/2) + b*(y-height/2);
-}
-
-void ImageData::xflip()
-{
-  double tmp[width];
-  for(int y = 0; y < height; y++)
-    {
-      memcpy(tmp,raw_data+y*width,sizeof(double)*width);
-      for(int x = 0; x < width; x++)
-       raw(x,y) = tmp[width-1-x];
-    }
-  double tmp2 = xmin;
-  xmin = xmax;
-  xmax = tmp2;
-}
-
-void ImageData::yflip()
-{
-  double tmp[width];
-  for (int y=0; y < height/2; y++)
-    {
-      memcpy(tmp,&raw(0,y),sizeof(double)*width);      
-      memcpy(&raw(0,y),&raw(0,height-y-1),sizeof(double)*width);
-      memcpy(&raw(0,height-y-1),tmp,sizeof(double)*width);
-    }
-  double tmp2 = ymin; 
-  ymin = ymax;
-  ymax = tmp2;
-}
-
-void ImageData::rotate_cw()
-{
-  double *tmp = new double [width*height]; // should not use the stack for large arrays: use new instead
-  memcpy(tmp, raw_data, sizeof(double)*width*height);
-  
-  for (int i=0; i<width; i++)
-    for (int j=0; j<height; j++)
-      raw_data[i*height+(height-1-j)] = tmp[j*width+i];
-  
-  double w = width;
-  width = height;
-  height = w;
-  
-  string tmpname = xname;
-  xname = yname; 
-  yname = tmpname;
-
-  // just trial and error...
-  double d1 = ymin;
-  double d2 = ymax;
-  ymin = xmax;
-  ymax = xmin;
-  xmin = d1;
-  xmax = d2;
-  delete [] tmp;
-}  
-
-void ImageData::rotate_ccw()
-{
-  double *tmp = new double [width*height]; // should not use the stack for large arrays: use new instead
-  memcpy(tmp, raw_data, sizeof(double)*width*height);
-  
-  for (int i=0; i<width; i++)
-    for (int j=0; j<height; j++)
-      raw_data[(width-1-i)*height+j] = tmp[j*width+i];
-
-  
-  double w = width;
-  width = height;
-  height = w;
-  
-  string tmpname = xname;
-  xname = yname; 
-  yname = tmpname;
-
-  // just trial and error...
-  double d1 = ymax;
-  double d2 = ymin;
-  ymin = xmin;
-  ymax = xmax;
-  xmin = d1;
-  xmax = d2;
-  delete [] tmp;
-}
-
-void ImageData::pixel_average(int nx, int ny)
-{
-  if (nx == 0 || ny == 0) return;
-
-  int w = width / nx;
-  int h = height / ny;
-  double tmp;
-
-  // This should work in-place, since we're only overwriting data we
-  // don't need anymore
-
-  // For in-place to work, we must have the inner loop iterating over
-  // i, since this is the data order axis!
-
-  for (int j=0; j<h; j++)
-    for (int i=0; i<w; i++)
-      {
-       tmp = 0;
-       for (int m=0; m<nx; m++)
-         for (int n=0; n<ny; n++)
-           tmp += raw(nx*i+m,ny*j+n)/nx/ny;   
-       raw_data[j*w+i] = tmp;
-      }
-  
-  width = w;
-  height = h;
-}
-
-void ImageData::switch_finder(double threshold, int avgwin, bool vert) //note: vert not yet implemented: is there a better way than cut and paste?
-{
-  int i,j,m,n;
-  double offset = 0;
-  double avg1 = 0 ;
-  double avg2 = 0 ;
-  threshold = fabs(threshold);
-  if (avgwin < 1) avgwin = 1;
-
-  // In principle, this is a very easy piece of code to write, but the
-  // it could be really, really amazingly useful!
-  for (j=0; j<height; j++)
-    {
-      offset = 0;
-      for (i=1; i<width; i++)
-       {
-         // Add running offset to current data
-         raw(i,j) += offset;
-         // Calculate avg from last "avgwin" points
-         for (m=1,n=0,avg1=0; m<=avgwin; m++)
-           if (i-m >= 0) 
-             {
-               avg1 += raw(i-m,j);
-               n++;
-             }
-         if (n>0) avg1 = avg1/n;
-         // If our next point deviates from the average by enough, then we've got switch
-         if (fabs(raw(i,j)-avg1) > threshold)
-           {
-             // Calculate the average for the next "avgwin" points too, and ignore subsequent points that might be a switch
-             avg2 = offset; n = 1;
-             for (m=0; m<=avgwin; m++)
-               if (i+m < width && fabs(raw(i+m,j)+offset-raw(i,j)) < threshold)
-                 {
-                   avg2 += raw(i+m,j) + offset;
-                   n++;
-                 }
-             avg2 = avg2/n;
-             avg2 = raw(i,j);
-             offset += avg1 - avg2;
-             raw(i,j) += avg1 - avg2; 
-           }
-       }
-    }
-}
-
-
-void ImageData::xderv()
-{
-  int w = width-1;
-  int h = height;
-
-  double xstep = (xmax - xmin)/w;
-
-  for (int j=0; j<h; j++)
-    for (int i=0; i<w; i++)
-      raw_data[j*w+i] = (raw(i+1,j) - raw(i,j))/xstep;
-  //raw_data[j*w+i] = (xmin<xmax) ? (raw(i+1,j) - raw(i,j)) : (raw(i,j) - raw(i+1,j));
-  
-  xmin = xmin+(xmax-xmin)/width/2;
-  xmax = xmax-(xmax-xmin)/width/2;
-  width = w;
-  height = h;
-}
-
-void ImageData::crop(int left, int right, int lower, int upper)
-{
-  // Let's be a bit clever: negative numbers on lower or right should
-  // be interpreted as counting from the left or bottom. Also
-  // implement smarter bounds checking (overflow large numbers).
-
-  if (left > width-1) left = left % (width);
-  if (right > width-1) right = right % (width);
-  if (upper > height-1) upper = upper % (height);
-  if (lower > height-1) lower = lower % (height);
-  
-  if (left < 0) left = left + (-left/width+1)*width - 1;
-  if (upper < 0) upper = upper + (-upper/height+1)*height - 1;
-  if (right <= 0) right = right + (-right/width+1)*width;
-  if (lower <= 0) lower = lower + (-lower/height+1)*height;
-
-  // Now check that things make sense
-  // Modified April 2010 -- the below crashed if right was at edge already.  
-  if (lower < upper) 
-    std::swap(upper,lower);
-  if (right < left) 
-    std::swap(left,right);
-
-  // Finally, make sure that we aren't cropping to nothing.
-  if(lower == upper)
-    if(upper > 0)
-      upper--;
-    else
-      lower++;
-  if(left == right)
-    if(left > 0)
-      left--;
-    else
-      right++;
-
-  int w = (right-left);
-  int h = (lower-upper);
-
-  for (int j=0; j<h; j++)
-   for (int i=0; i<w; i++)
-     raw_data[j*w+i] = raw(i+left, j+upper);
-  
-  double newxmin = getX(left);
-  double newxmax = getX(right-1);
-  
-  double newymin = getY(lower-1);
-  double newymax = getY(upper);
-  
-  xmin = newxmin; xmax = newxmax;
-  ymin = newymin; ymax = newymax;
-
-  width = w;
-  height = h;
-}
-
-void ImageData::even_odd(bool even, bool fwd_rev)
-{
-  int h = height/2;
-  if (!even) h -= height%2;
-
-  int off = even ? 0 : 1;
-
-  if (even || !fwd_rev)
-    {
-      for (int j=0; j<h; j++)
-       memcpy(&raw(0,j), &raw(0,2*j+off), sizeof(double)*width);
-    }
-  else
-    {
-      for (int j=0; j<h; j++)
-       for (int i=0; i<width; i++)
-         raw(i,j) = raw(width-1-i,2*j+off);
-    }
-
-  height = h;
-}
-  
-
-void ImageData::yderv()
-{
-  int w = width;
-  int h = height-1;
-
-  // Another one of those negative signs...
-  double ystep = -(ymax - ymin)/h;
-
-  for (int j=0; j<h; j++)
-    for (int i=0; i<w; i++)
-      raw_data[j*w+i] = (raw(i,j+1) - raw(i,j))/ystep;
-      //raw_data[j*w+i] = (ymin>ymax) ? (raw(i,j+1) - raw(i,j)) : (raw(i,j) - raw(i,j+1));
-  
-  ymin = ymin+(ymax-ymin)/height/2;
-  ymax = ymax-(ymax-ymin)/height/2;
-  width = w;
-  height = h;
-}
-
-void ImageData::ederv(double pscale, double nscale)
-{
-  int w = width;
-  int h = height-1;
-  int h0 = -ymin * h / (ymax - ymin);
-  printf("ymin is %g, ymax is %g, h is %d, h0 is %d\n",ymin,ymax,h,h0);
-  for (int j=0; j<h; j++)
-    for (int i=0; i<w; i++)
-      {
-       int sign=1;
-       if(j < h0)
-         sign=-1;
-       else if ( j == h0 || j+1 == h0) // Not clear what to do exactly at zero.
-         sign = 0;
-       raw_data[j*w+i] = ((ymin>ymax) ? (raw(i,j+1) - raw(i,j)) : (raw(i,j) - raw(i,j+1))) * sign;
-       if(raw_data[j*w+i] < 0)
-         raw_data[j*w+i] *= nscale;
-       else
-         raw_data[j*w+i] *= pscale;
-      }
-  
-  ymin = ymin+(ymax-ymin)/height/2;
-  ymax = ymax-(ymax-ymin)/height/2;
-  width = w;
-  height = h;
-}
-
-void ImageData::grad_mag(double axis_bias)
-{
-  printf("%g bias\n",axis_bias);
-  int w = width;
-  int h = height;
-  double *tmpx = (double *)malloc(sizeof(double) * width * height);
-
-  memcpy(tmpx,raw_data,sizeof(double)*width*height);
-  xderv();
-  width = w;
-  height = h;
-  swap(tmpx,raw_data);
-  yderv();
-  width = w;
-  height = h;
-  double *result = (double *)malloc(sizeof(double) * (width-1) * (height-1));
-  for(int x = 0; x < width-1; x++)
-    for(int y = 0; y < height-1; y++)
-      {
-       double g1 = tmpx[x+(width-1)*y];
-       double g2 = raw_data[x+width*y];
-       result[x+(width-1)*y] = sqrt(g1*g1*(1.0-axis_bias)+g2*g2*axis_bias);
-      }
-  memcpy(raw_data,result,sizeof(double)*(width-1)*(height-1));
-  free(result);
-  free(tmpx);
-  width = width-1;
-  height = height-1;
-}
-
-void ImageData::equalize() // Hist. eq.. We work on the quantized data here for simplicity.
-{
-  quantize();
-  int cumsum[QUANT_MAX+1];
-  int mapping[QUANT_MAX+1];
-
-  // Generate the cumulative sum.
-  memset(cumsum, 0, sizeof(cumsum));
-  int *p = quant_data;
-  for(int i = 0; i < width*height; i++)
-    {
-      assert(*p <= QUANT_MAX && *p >= 0);
-      cumsum[*p++]++;
-    }
-  for(int i = 1; i <= QUANT_MAX; i++)
-    cumsum[i] += cumsum[i-1];
-
-  // Find the minimum value.
-  int minval = -1;
-  for(int i = 0; i <= QUANT_MAX; i++)
-    if(cumsum[i] != 0)
-      {
-       minval = cumsum[i];
-       break;
-      }
-  assert(minval >= 0);
-  
-  // Generate the mapping; see http://en.wikipedia.org/wiki/Histogram_equalization
-  for(int i = 0; i <= QUANT_MAX; i++)
-    {
-      mapping[i]=round((1.0*cumsum[i]-1.0*minval)*(QUANT_MAX*1.0)/(1.0*width*height-1.0*minval));
-    }
-
-  // Apply the mapping using an extra-clever linear interpolation on the floating point data!  Yay!
-  for(int i = 0; i < width*height; i++)
-    {
-      double raw = raw_data[i];
-      double v = 1.0*(raw-qmin)*QUANT_MAX/(qmax-qmin);
-      assert(v >= 0 && floor(v) < QUANT_MAX);
-      double dv = v-floor(v);
-      assert(dv >= 0);
-      assert(dv <= 1.0);
-      double quant = mapping[(int)v]*(1.0-dv)+mapping[(int)(v+0.5)]*dv;
-      raw_data[i] = quant_to_raw(quant);
-    }
-}
-
-void ImageData::dderv(double theta) // theta in degrees!
-{
-  int w = width;
-  int h = height;
-  double *tmpx = (double *)malloc(sizeof(double) * width * height);
-
-  memcpy(tmpx,raw_data,sizeof(double)*width*height);
-  xderv();
-  width = w;
-  height = h;
-  swap(tmpx,raw_data);
-  yderv();
-  width = w;
-  height = h;
-  double *result = (double *)malloc(sizeof(double) * (width-1) * (height-1));
-  double t1=cos(theta*M_PI/180.0);
-  double t2=sin(theta*M_PI/180.0);
-  for(int x = 0; x < width-1; x++)
-    for(int y = 0; y < height-1; y++)
-      {
-       double g1 = tmpx[x+(width-1)*y];
-       double g2 = raw_data[x+width*y];
-       result[x+(width-1)*y] = g1*t1+g2*t2;
-      }
-  memcpy(raw_data,result,sizeof(double)*(width-1)*(height-1));
-  free(result);
-  free(tmpx);
-  width = width-1;
-  height = height-1;
-}
-
-
-void ImageData::make_lowpass_kernel(double *data, double dev, int size, ImageData::lowpass_kernel_t type)
-{
-  double center = floor(size/2.0);
-  double sum = 0.0;
-  for(int i = 0; i < size; i++)
-    {
-      double dx = (static_cast<double>(i)-center);      
-      dx /= dev;
-      double y;
-      switch(type)
-       {
-       case LOWPASS_GAUSS:
-         y = exp(-(dx*dx)/(2.0));
-         break;
-       case LOWPASS_EXP:
-         y = exp(-fabs(dx)*sqrt(2.0)); 
-         break;
-       case LOWPASS_LORENTZ:
-         // Lorentzian has no std. dev, so set FWHM = sigma
-         y = 1.0/(dx*dx+1.0); 
-         break;
-       case LOWPASS_THERMAL: // Derivative of Fermi function; dev is temperature in pixels
-         y = exp(dx)/(dev*(1+exp(dx))*(1+exp(dx)));
-         break;
-       default:
-         assert(0);
-       }
-      sum += y;
-      data[i] = y;
-    }
-  sum = 1.0/sum;
-  for(int i = 0; i < size; i++)
-    data[i] *= sum;
-}
-
-// This executes a gaussian blur low pass filter
-void ImageData::lowpass(double xsize, double ysize, ImageData::lowpass_kernel_t type, double mult)
-{
-  int kernel_size;
-  double sum;
-
-  if (xsize == 0 && ysize == 0)
-    return;
-
-  kernel_size = xsize*mult;
-  if (kernel_size > 0 && kernel_size < mult) kernel_size = mult;
-      
-  if (kernel_size > 0)
-    {
-      // For really big images, I think it is better not to reallocate an entire 2D image array (?)
-      double filtered[width]; 
-      double kernel[kernel_size];
-      make_lowpass_kernel(kernel, xsize, kernel_size,type);
-      int kernel_offset = -kernel_size/2;
-
-      for(int y = 0; y < height; y++)
-       {
-         for(int x = 0; x < width; x++)
-           {
-             sum = 0.0;
-             for(int k = 0; k < kernel_size; k++)
-               {
-                 int nx = x + k + kernel_offset;
-                 if(nx < 0) nx = 0;
-                 if(nx >= width) nx = width-1;
-                 sum += kernel[k]*raw(nx,y);
-               }
-             filtered[x] = sum;
-           }
-         memcpy(&raw(0,y), filtered, sizeof(double)*width);
-       }
-    }
-
-  kernel_size = ysize*mult;
-
-  if (kernel_size > 0 && kernel_size < mult) kernel_size = mult;
-  
-  if (kernel_size > 0)
-    {
-      double filtered[height]; 
-      double kernel[kernel_size];
-      make_lowpass_kernel(kernel, ysize, kernel_size,type);
-      int kernel_offset = -kernel_size/2;
-
-      for(int x = 0; x < width; x++)
-       {
-         for(int y = 0; y < height; y++)
-           {
-             sum = 0.0;
-             for(int k = 0; k < kernel_size; k++)
-               {
-                 int ny = y + k + kernel_offset;
-                 if(ny < 0) ny = 0;
-                 if(ny >= height) ny = height-1;
-                 sum += kernel[k]*raw(x,ny);
-               }
-             filtered[y] = sum;
-           }
-         for(int y = 0; y < height; y++)
-           raw(x,y) = filtered[y];  // can't use memcpy here
-       }
-    }
-}
-
-// This could be made much more memory efficent if need be; see lowpass.
-void ImageData::highpass(double xsize, double ysize, double passthrough, ImageData::lowpass_kernel_t type, double mult)
-{
-  double *d2 = new double[width*height];
-  assert(d2);
-  memcpy(d2,raw_data,sizeof(double)*width*height);
-  lowpass(xsize,ysize,type,mult);
-  for(int x = 0; x < width; x++)
-    for(int y = 0; y < height; y++)
-      raw(x,y)=d2[y*width+x]-(1.0-passthrough)*raw(x,y);  
-  delete[] d2;
-}
-
-void ImageData::notch(double xlow, double xhigh, double ylow, double yhigh, double mult) // width is width of mask to use measured in units of xsize, ysize
-{
-  lowpass(xlow,ylow,LOWPASS_GAUSS,mult);
-  highpass(xhigh,yhigh,0.0,LOWPASS_GAUSS,mult);
-}
-
-// Despeckle an image with a median filter
-// Helper functions
-inline static int median_3(double a, double b, double c)
-{
-  if(((a <= b) && (b <= c)) || ((c <= b) && (b <= a)))
-    return b;
-  if(((b <= c) && (c <= a)) || ((a <= c) && (c <= b)))
-    return c;
-  return a;
-}
-static int compare_doubles(const void *ap, const void *bp)
-{
-  double a = *reinterpret_cast<const double *>(ap);
-  double b = *reinterpret_cast<const double *>(bp);
-  if(a < b)
-    return -1;
-  if(a == b)
-    return 0;
-  return 1;
-}
-inline static int median_3x3(double *r1, double *r2, double *r3)
-{
-  double tmp[9];
-  memcpy(tmp, r1, sizeof(double)*3);
-  memcpy(tmp+3, r2, sizeof(double)*3);
-  memcpy(tmp+6, r3, sizeof(double)*3);
-  qsort(tmp, 9, sizeof(double), compare_doubles);
-  return tmp[4];
-}
-// Main functions
-void ImageData::despeckle(bool d_x, bool d_y)
-{
-  if(d_x && d_y)
-    {
-      double *tmp = new double[width * height];
-      memcpy(tmp,raw_data,sizeof(double)*width*height);
-      for(int x = 1; x < width-1; x++)
-       for(int y = 1; y < height-1; y++)
-         raw(x,y) = median_3x3(tmp+(y-1)*width+x-1,tmp+y*width+x-1, tmp+(y+1)*width+x-1);
-      delete[] tmp;
-    }
-  else if(d_x)
-    {
-      double tmp[width];
-      for(int y = 0; y < height; y++)
-       {
-         for(int x = 1; x < (width-1); x++)
-           tmp[x] = median_3(raw(x-1,y),raw(x,y),raw(x+1,y));
-         for(int x = 1; x < (width-1); x++)
-           raw(x,y) = tmp[x];
-       }
-    }
-  else if(d_y)
-    {
-      double tmp[height];
-      for(int x = 0; x < width; x++)
-       {
-         for(int y = 1; y < (height-1); y++)
-           tmp[y] = median_3(raw(x,y-1),raw(x,y),raw(x,y+1));
-         for(int y = 1; y < (height-1); y++)
-           raw(x,y) = tmp[y];
-       }
-    }   
-}
-
-
-MTX_Data::MTX_Data()
-{
-  size[0] = size[1] = size[2] = 0;
-  data_loaded = 0;
-  progress_gui = true;
-  delft_raw_units = true;
-  delft_settings = false;
-  win = NULL;
-}
-
-MTX_Data::~MTX_Data()
-{
-  clear();
-}
-
-void MTX_Data::open_progress_gui()
-{
-  if (win == NULL)
-    {
-      win = new Fl_Double_Window(220,25, "Loading file...");
-      win->begin();
-      msg = new Fl_Output(0,0,220,25);
-      msg->color(FL_BACKGROUND_COLOR);
-      win->end();
-    }
-  win->show();
-}
-
-void MTX_Data::close_progress_gui()
-{
-  win->hide();
-}
-
-
-int MTX_Data::load_file(const char *name)
-{
-  FILE *fp = fopen(name, "rb");
-  if(fp == NULL)
-    badfile("Unable to open file \"%s\": %s\n",name,strerror(errno));
-  filename = name;
-
-  char buf[MTX_HEADER_SIZE];
-  int i,j,k;
-  fgets(buf, sizeof(buf), fp);
-  int bytes = 8;
-
-  char units_header[MTX_HEADER_SIZE]; // 256 characters is not long enough...
-  int found_units = 0;
-
-  // First read the header information, which include the axis ranges and names
-
-  if (strncmp(buf, "Units", 5) == 0) 
-    {
-      found_units = 1;
-      strncpy(units_header, buf, sizeof(buf));
-      fgets(buf, sizeof(buf), fp); // fixme ; check for errors here.
-    }  
-  if (sscanf(buf, "%d %d %d", &size[0], &size[1], &size[2]) != 3)
-    badfilec("Malformed mtx header: %s", filename.c_str());
-  if (sscanf(buf, "%*d %*d %*d %d", &bytes) != 1)
-    warn( "Legacy mtx file found (%s): assuming double data (bytes = %d)\n", filename.c_str(), bytes);
-
-  clear();
-  data = new double [size[0]*size[1]*size[2]]; 
-  data_loaded = 1;
-
-
-  bool progress = (size[0]*size[1]*size[2]) > 100*100*100*5;
-
-  int t1 = time(NULL);
-
-  if (progress && progress_gui)
-    {
-      open_progress_gui();
-      msg->value("Reading file: 0%");
-    }
-
-  static char msgbuf[256];
-  
-  // Now actually read the data in from the file
-
-  for (i=0; i<size[0]; i++)
-    {
-      for (j=0; j<size[1]; j++)
-       for (k=0; k<size[2]; k++)
-         {
-           if (bytes == 4)
-             {
-               float tmp;
-               if (fread(&tmp, bytes, 1, fp) != 1) 
-                 badfilec( "Short read on mtx file: %s", filename.c_str());
-               if (isnan(tmp)) warn( "nan at %d %d %d", i, j, k);
-               getData(i,j,k) = tmp;
-             }
-           else if (bytes == 8)
-             {
-               double tmp;
-               if (fread(&tmp, bytes, 1, fp) != 1) 
-                 badfilec( "Short read on mtx file: %s", filename.c_str()); 
-               getData(i,j,k) = tmp;
-             }
-           else 
-             badfile( "Unsupported number of bytes %d", bytes);
-         }
-      if (progress_gui)
-       Fl::check();
-      if (progress)
-       {
-         snprintf(msgbuf,sizeof(msgbuf), "Reading File: %.0f%%", 1.0*i/(size[0]-1)*100.0);
-         if (progress_gui)
-           msg->value(msgbuf);
-         else 
-           info("%s\r", msgbuf);
-       }
-    }
-
-  if (!progress_gui && progress)
-    info("\n");
-  
-  if (progress_gui && progress)
-    close_progress_gui();
-
-  int t2 = time(NULL);
-  // Output timing info here if you want
-
-  if (found_units)
-    {
-      char *p = strtok(units_header, ",");
-      p = strtok(0, ",");
-      while (isspace(*p)) p++;
-      dataname = p;
-      for (int i = 0; i<3; i++)
-       {
-         p = strtok(0, ","); 
-         while (isspace(*p)) p++;
-         axisname[i] = p;
-         p = strtok(0, ","); 
-         while (isspace(*p)) p++;
-         sscanf(p, "%lf", &axismin[i]);
-         p = strtok(0, ","); 
-         while (isspace(*p)) p++;
-         sscanf(p, "%lf", &axismax[i]);
-       }
-    }
-  else
-    {
-      dataname = "Data Value";
-      axismin[0] = axismin[1] = axismin[2] = 0;
-      axismax[0] = size[0]; axisname[0] = "X";
-      axismax[1] = size[1]; axisname[1] = "Y";
-      axismax[2] = size[2]; axisname[2] = "Z";
-    }
-
-  data_loaded = 1;
-  fclose(fp);
-  return 0;
-} 
-
-
-// Load data from a gnuplot formatted files into a 3D matrix. 
-// Here, we use the index number as the third dimensiont of the 3d matrix. 
-// The user must specify which column of the gnuplot file the data should be read from.
-
-int MTX_Data::load_gp_index(const char *name, int colnum)
-{
-  vector<double> datavec;
-  double datatmp;
-  char linebuffer[LINESIZE];
-  char *p;
-
-
-  char sep[] = " \t\n\r";
-
-  FILE *fp = fopen(name, "rb");
-  if(fp == NULL)
-    badfile("Unable to open file \"%s\": %s\n",name,strerror(errno));
-  
-  int lines_per_block; // size of the datablocks 
-  int line;
-
-  int blocks_per_index;
-  int block;
-  
-  int num_indices;
-
-  bool first_block = true;
-  bool first_index = true;
-
-  line = lines_per_block = 0;
-  block = blocks_per_index = 0;
-  num_indices = 0;
-
-  int nread = 0;
-  bool block_ended = false;
-  bool index_ended = false;
-  int nptread = 0;
-
-  bool found_data;
-
-  int t1 = time(NULL);
-  if (progress_gui)
-    {
-      open_progress_gui();
-      msg->value("Lines read: 0");
-    }
-
-  while (1)
-    {
-      nread++;
-      if (fgets(linebuffer, LINESIZE, fp) == NULL)
-       break;
-         
-      // Figure out what kind of line this is
-      // Get rid of spaces at beginning of line
-      for(p = linebuffer; *p != 0 && isspace(*p); p++)
-       ;
-      // Ignore comment lines
-      if(*p == '#')
-       continue;
-      // A blank line signals the end of a datablock or of an index
-      if (*p == '\n' || *p == 0)
-       {
-         if (!block_ended) // We have reached the end of a block
-           {
-             if (first_block) //we found the end of the first block
-               { 
-                 if (line == 0) //ignore blank lines at the top of the file
-                   continue; 
-                 lines_per_block = line;
-                 first_block = false;
-               }
-             if (line != lines_per_block) 
-               {
-                 info("block %d ended early, assuming incomplete file\n");
-                 break;
-               }
-             //badfilec( "block %d at line %d has %d lines < %d\n", 
-             //block, nread, line, lines_per_block);
-             line = 0;
-             block_ended = true; 
-             block++;
-             continue;
-           }
-         if (!index_ended)  // this means we have found two blank lines
-           {
-             if (first_index)
-               {
-                 blocks_per_index = block;
-                 first_index = false;
-               }
-             if (block != blocks_per_index) 
-               badfilec( "index %d at line %d has %d blocks < %d\n", 
-                         num_indices, nread, block, blocks_per_index);
-             block = 0;
-             index_ended = true;
-             num_indices++;
-             continue;
-           }
-         else //discard any addional blank lines after we finish an index
-           continue; 
-       }
-      
-      // This line contains real data
-      index_ended = block_ended = false;
-      
-      // Parse the line and perform the conversions
-      int col = 0;
-      found_data = false;
-      p = strtok(linebuffer, sep);
-      while (p != NULL)
-       {
-         if (sscanf(p, "%lf", &datatmp) != 1)
-           warn("mtx gnuplot: invalid data at line %d col %d: \"%s\", copying last read value\n", nread, col, p);
-         if (col == colnum)
-           {
-             datavec.push_back(datatmp);
-             found_data = true;
-             break;
-           }
-         col++;
-         p = strtok(0, sep);
-       }
-      
-      if (!found_data)
-       badfile( "Failed to find data in column %d at line %d", colnum, nread);
-      nptread++;
-      line++;
-
-      if (nread%100 == 0)
-       {
-         static char buf[256];
-         snprintf(buf, sizeof(buf), "Lines read: %d", nread);
-         if (progress_gui)
-           {
-             msg->value(buf);
-             Fl::check();
-           }
-         else
-           info("%s\r", buf);
-       }
-    }
-
-  if (progress_gui)
-    close_progress_gui();
-  else
-    info("\n");
-
-  fclose(fp);
-
-  int t2 = time(NULL);
-
-  info("points: %d of %d\n", nptread, lines_per_block * blocks_per_index * num_indices);
-  info("lines: %d of %d\n", line, lines_per_block);
-  info("blocks: %d of %d\n", block, blocks_per_index);
-  info("indices: %d\n", num_indices);
-
-  if (blocks_per_index == 0) // if we're still reading the first index...
-    {
-      blocks_per_index = block+1;
-      info("not yet finished the first index, settigns blocks_per_index to %d", blocks_per_index);
-    }
-
-  //if (nptread < lines_per_block * blocks_per_index * num_indices)
-  if (block != 0 || line != 0) // we didn't find the end of and index or the end of a line.
-    {
-      num_indices++;
-      int npts_needed = lines_per_block * blocks_per_index * num_indices;
-      int nadd = npts_needed - nptread;
-      info("looks like an incomplete file\n");      
-      info("will assume size is %d, %d, %d", lines_per_block, blocks_per_index, num_indices);
-      info("read %d data points, need %d\n", nptread, npts_needed);
-      info("adding %d points with last value found in file %e", nadd, datatmp);
-      if (nadd > 0)
-       for (int i = 0; i < nadd ; i++)
-         datavec.push_back(datatmp);
-    }
-
-//   info( "lines per block %d blocks per index %d num indices %d\n", lines_per_block, blocks_per_index, num_indices);
-
-//   info("Number of points read: %d\n", nptread);
-//   info("Number of points expe: %d\n", lines_per_block * blocks_per_index * num_indices);
-//   info("Lines per block:    %d\n", lines_per_block);
-//   info("Line in last block: %d\n", line);
-
-  if (lines_per_block == 0 || blocks_per_index == 0 || num_indices == 0)
-    return -1;
-
-  // When loading data linearly into MTX matrix from gnuplot3d format, we get the following data ordering:
-  // X = loop 2 = index nimber
-  // Y = loop 1 = block
-  // Z = sweep  = point number
-
-  size[0] = lines_per_block; 
-  size[1] = blocks_per_index; 
-  size[2] = num_indices; 
-
-  if (size[0]*size[1]*size[2] == 0)
-    {
-      info("file has no complete lines\n");
-      return -1;
-    }
-
-  clear(); 
-  data = new double [size[0]*size[1]*size[2]]; 
-  data_loaded = 1; 
-
-  for (int k=0; k<size[2]; k++)
-    for (int j=0; j<size[1]; j++)
-      for (int i=0; i<size[0]; i++)
-       getData(i,j,k) = datavec[k*size[1]*size[0]+j*size[0]+i];
-
-  dataname = "Data Value";
-  axismin[0] = axismin[1] = axismin[2] = 0;
-  axismax[0] = size[0]; axisname[0] = "X";
-  axismax[1] = size[1]; axisname[1] = "Y";
-  axismax[2] = size[2]; axisname[2] = "Z";
-  if (parse_txt) parse_delft_txt(name, false);
-  return 0;
-}
-
-// Again loading gnuplot formatted data into a 3d matrix
-// However, this time, indices are ignored and the 3rd 
-// dimension of the matrix is used to load data from 
-// the different columns of the data file.
-  
-int MTX_Data::load_gp_cols(const char *name)
-{
-  vector<double> datavec;
-  double datatmp;
-  char linebuffer[LINESIZE];
-  char *p;
-
-  char sep[] = " \t\n\r";
-
-  FILE *fp = fopen(name, "rb");
-  if(fp == NULL)
-    badfile("Unable to open file \"%s\": %s\n",strerror(errno));
-
-  int col;
-  int cols_per_line;
-  
-  int line;
-  int lines_per_block;
-
-  int num_blocks; // number of datablocks so far (note: we count
-                    // indexes (ie. blocks separated by two blank
-                    // lines) also as datablocks
-  
-  bool first_line = true;
-  bool first_block = true;
-
-  col = cols_per_line = 0;
-  line = lines_per_block = 0;
-  num_blocks = 0;
-
-  int nread = 0;
-
-  int t1 = time(NULL);
-  if (progress_gui)
-    {
-      open_progress_gui();
-      msg->value("Lines read: 0");
-    }
-
-  while (1)
-    {
-      nread++;
-      if (fgets(linebuffer, LINESIZE, fp) == NULL)
-       break;
-      
-      // Figure out what kind of line this is
-
-      // Get rid of spaces at beginning of line
-      for(p = linebuffer; *p != 0 && isspace(*p); p++)
-       ;
-      
-      // Ignore comment lines
-      if(*p == '#')
-       continue;
-
-      // A blank line signals the end of a datablock
-      if (*p == '\n' || *p == 0)
-       {
-         if (line == 0) //ignore blank lines at the top of the file and extra blank lines between blocks
-           continue; 
-         num_blocks++;
-         if (first_block) //we found the end of the first block
-           { 
-             lines_per_block = line;
-             first_block = false;
-           }
-         if (line != lines_per_block) //this is possible if the dataset is not done yet, so we'll be nice and not exit
-           {
-             info("Block size does not match on datablock %d (line %d)!  Ending file read and discarding block.\n", num_blocks, nread);
-             num_blocks--;
-             break;
-           }
-         line = 0;
-         continue;
-       }
-
-      // Parse the line and perform the conversions
-      col = 0;
-      p = strtok(linebuffer, sep);
-      while (p != NULL)
-       {
-         if (sscanf(p, "%lf", &datatmp) != 1)
-           info("mtx gnuplot: invalid data at line %d col %d: \"%s\", copying last read value\n", nread, col, p);
-         datavec.push_back(datatmp);
-         col++;
-         if (!first_line && col == cols_per_line)
-           break;
-         p = strtok(0, sep);
-       }
-      if (first_line)
-       {
-         first_line = false;
-         cols_per_line = col;
-         //info( "gp_cols: found %d columns\n", cols_per_line);
-       }
-      line++;
-         
-      if (nread%100 == 0)
-       {
-         static char buf[256];
-         snprintf(buf, sizeof(buf), "Lines read: %d", nread);
-         if (progress_gui)
-           {
-             msg->value(buf);
-             Fl::check();
-           }
-         else
-           info("%s\r", buf);
-       }
-
-      // We will ignore extra columns, but we will be cowardly and exit if
-      // we don't find enough columns
-      if (col < cols_per_line)
-       {
-         info("Too few columns at line %d, assuming incomplete file\n", nread);
-         break;
-       }
-    }
-
-  fclose(fp);
-
-  if (progress_gui)
-    close_progress_gui();
-  else
-    info("\n");
-
-  //  info( "gp_cols: cols_per_line %d lines_per_block %d num_blocks %d\n", 
-  //     cols_per_line, lines_per_block, num_blocks);
-  
-  int t2 = time(NULL);
-  
-  //info("Read %d lines at %.3f thousand lines per second\n", nread, 1.0*nread/(t2-t1)/1e3);
-
-  size[0] = cols_per_line;
-  size[1] = lines_per_block;
-  size[2] = num_blocks;
-
-  if (size[0]*size[1]*size[2] == 0)
-    {
-      warn("file has no complete lines\n");
-      return -1;
-    }
-
-  clear();
-  data = new double [size[0]*size[1]*size[2]];
-  data_loaded = 1;
-
-  for (int k=0; k<size[2]; k++)
-    for (int j=0; j<size[1]; j++)
-      for (int i=0; i<size[0]; i++)
-       getData(i,j,k) = datavec[k*size[1]*size[0]+j*size[0]+i];
-
-  dataname = "Data Value";
-  axismin[0] = axismin[1] = axismin[2] = 0;
-  axismax[0] = size[0]; axisname[0] = "X";
-  axismax[1] = size[1]; axisname[1] = "Y";
-  axismax[2] = size[2]; axisname[2] = "Z";
-  if (parse_txt) parse_delft_txt(name, true);
-  return 0;
-}
-
-void MTX_Data::get_settings(const char *comments)
-{
-  char *p = strstr(comments, "Loop 2");
-  p = strstr(p, "DAC");
-  
-  info("getting settings\n");
-  char buf[256];
-  settings = " at ";
-  double val;
-  for (int i=1; i<= 16; i++) 
-    {
-      //getchar();
-      p = strchr(p, ' ');
-      if (sscanf(p, "%lf", &val) == 1)
-       {
-         if (val != 0.0)
-           {
-             sprintf(buf, "D%d=%g ", i, val);
-             settings += buf;
-           }
-       }
-      p = strstr(p, "DAC");
-    }
-  info("settings:\n%s\n", settings.c_str());
-}
-      
-           
-
-
-// *ident is the text at the start of the line, line "Sweep " or "Loop 1".
-  
-void MTX_Data::parse_comments(char *comments, const char *ident, int *dac, int *size, char *name, double *range)
-{
-  double mult;
-  char *p;
-  char buf[256];
-
-  // We never use the pulse stuff: recently modified a copy of the
-  // labview to use the pulse drop down items for a second RF
-  // generator.
-  string extra_names[] = {
-    "RF Freq",
-    "RF Power",
-    "RF2 Freq", 
-    "RF2 Power",
-    "Pulse amp min",
-    "Pulse amp max",
-    "Pulse amp",
-    "Pulse offset",
-    "Magnetic Field (T)"};
-  
-  // First get the "dac" number
-  p = strstr(comments, ident);
-  sscanf(p+strlen(ident), "%d", dac);
-
-  // Now get the number of steps
-  p = strstr(comments, ident);
-  p = strstr(p, "in ");
-  sscanf(p+3, "%d", size);
-
-  // If we're sweeping "nothing", then this is easy.
-  if (*dac == 0)
-    {
-      snprintf(name, 256, "%sNumber", ident); //something like "Loop 1 Number"
-      range[0] = 0;
-      range[1] = *size;
-      return;
-    }
-      
-  // If this is a real DAC, then find the DAC name and the multiplier
-  // from the comments
-  if (*dac < 17)
-    {
-      int n = *dac - 1; // in commments, DAC1 becomes DAC0...
-      snprintf(buf, 256, "DAC%d \"", n);
-      p = strstr(comments, buf);
-      strncpy(name, p+strlen(buf), 256);
-      p = strchr(name, '"');
-      *p = 0;
-  
-      p = strstr(comments, buf);
-      p = strchr(p, '"');
-      p = strchr(p+1, '"');
-      if (sscanf(p+1, "%lf", &mult) != 1) 
-       {
-         warn("error reading mult\n");
-         mult = 1;
-       }
-    }
-  else //otherwise, use the hard coded names for RF Freq, ..., Magnetic Field
-    {
-      mult = 1;
-      int n = *dac-17;
-      strncpy(name, extra_names[n].c_str(), 256);
-    }
-     
-  // Now find the range
-  p = strstr(comments, ident);
-  p = strstr(p, "from ");
-  sscanf(p+5, "%lf", &range[0]);
-  p = strstr(p, "to ");
-  sscanf(p+3, "%lf", &range[1]);
-
-  if (!delft_raw_units)
-    {
-      range[0] *= mult;
-      range[1] *= mult;
-    }
-
-  // We're done!
-}
-
-// what a mess...i should really rewrite the labview code to output meta.txt files...
-  
-void MTX_Data::parse_var2_comments(char *comments, const char *ident, int *dac, char *name, double *range)
-{
-  double mult;
-  char *p;
-  char buf[256];
-  
-  info("parsing var2 for %s\n", ident);
-
-  string extra_names[] = {
-    "RF Freq",
-    "RF Power",
-    "Pulse Width",
-    "Pulse Freq",
-    "Pulse amp min",
-    "Pulse amp max",
-    "Pulse amp",
-    "Pulse offset",
-    "Magnetic Field (T)"};
-  
-  // First get the "dac" number
-  if ((p = strstr(comments, ident)) == NULL)
-    {
-      // bug in some versions of the labview...
-      if (strcmp(ident, "Loop 1 var2") == 0)
-       {
-         p = strstr(comments, "Loop 1");
-         p = strstr(p, "Sweep var2");
-         if (p == NULL)
-           {
-             info("failed to correct for buggy labview ident %e", ident);
-             return;
-           }
-       }
-      else if (strcmp(ident, "Loop 2 var2") == 0)
-       {
-         p = strstr(comments, "Loop 2");
-         p = strstr(p, "Sweep var2");
-         if (p == NULL)
-           {
-             info("failed to correct for buggy labview ident %e", ident);
-             return;
-           }
-       }
-      else
-       {
-         info("failed to find identifier %s\n", ident);
-         return;
-       }
-    }
-
-  sscanf(p+strlen(ident), "%d", dac);
-  
-  // If we're sweeping "nothing", then this is easy.
-  if (*dac == 0)
-    {
-      snprintf(name, 256, "%sNumber", ident); //something like "Loop 1 Number"
-      range[0] = 0;
-      range[1] = *size;
-      return;
-    }
-      
-  // If this is a real DAC, then find the DAC name and the multiplier
-  // from the comments
-  if (*dac < 17)
-    {
-      int n = *dac - 1; // in commments, DAC1 becomes DAC0...
-      snprintf(buf, 256, "DAC%d \"", n);
-      p = strstr(comments, buf);
-      strncpy(name, p+strlen(buf), 256);
-      p = strchr(name, '"');
-      *p = 0;
-  
-      p = strstr(comments, buf);
-      p = strchr(p, '"');
-      p = strchr(p+1, '"');
-      if (sscanf(p+1, "%lf", &mult) != 1) 
-       {
-         warn("error reading mult\n");
-         mult = 1;
-       }
-    }
-  else //otherwise, use the hard coded names for RF Freq, ..., Magnetic Field
-    {
-      mult = 1;
-      int n = *dac-17;
-      strncpy(name, extra_names[n].c_str(), 256);
-    }
-     
-  // Now find the range
-  if ((p = strstr(comments, ident)) == NULL)
-    {
-      // bug in some versions of the labview...
-      if (strcmp(ident, "Loop 1 var2") == 0)
-       {
-         p = strstr(comments, "Loop 1");
-         p = strstr(p, "Sweep var2");
-         if (p == NULL)
-           {
-             info("failed to correct for buggy labview ident %e", ident);
-             return;
-           }
-       }
-      else if (strcmp(ident, "Loop 2 var2") == 0)
-       {
-         p = strstr(comments, "Loop 2");
-         p = strstr(p, "Sweep var2");
-         if (p == NULL)
-           {
-             info("failed to correct for buggy labview ident %e", ident);
-             return;
-           }
-       }
-      else
-       {
-         info("failed to find identifier %s\n", ident);
-         return;
-       }
-    }
-
-  p = strstr(p, "from ");
-  sscanf(p+5, "%lf", &range[0]);
-  p = strstr(p, "to ");
-  sscanf(p+3, "%lf", &range[1]);
-
-  if (!delft_raw_units)
-    {
-      range[0] *= mult;
-      range[1] *= mult;
-    }
-
-  // We're done!
-}
-
-void MTX_Data::parse_delft_txt(const char *name, bool columns)
-{
-  char txtname[256];
-  char *p;
-  strncpy(txtname, name, 256);
-  if ((p = strstr(txtname, ".dat")) == NULL)
-    {
-      warn("filename %s does not contain .dat", name);
-      return;
-    }
-  *p=0;
-  strcat(txtname, ".txt");
-
-  //info("Parsing delft txt file %s\n", txtname);
-  FILE *fp = fopen(txtname, "r");
-  if (fp == NULL)
-    {
-      warn("Error opening file %s: %s\n", txtname, strerror(errno));
-      return;
-    }
-          
-  char comments[1024*10];
-  fread(comments, 1, 1024*10, fp);
-  fclose(fp);
-
-  // Read sweep settings
-  int sweep_steps;
-  int loop1_steps;
-  int loop2_steps;
-
-  double sweep_range[2];
-  double loop1_range[2];
-  double loop2_range[2];
-
-  int sweep_dac;
-  int loop1_dac;
-  int loop2_dac;
-
-  char sweep_name[256];
-  char loop1_name[256];
-  char loop2_name[256];
-
-  parse_comments(comments, "Sweep ", &sweep_dac, &sweep_steps, sweep_name, sweep_range);
-  parse_comments(comments, "Loop 1 ", &loop1_dac, &loop1_steps, loop1_name, loop1_range);
-  parse_comments(comments, "Loop 2 ", &loop2_dac, &loop2_steps, loop2_name, loop2_range);
-
-  double sweep_var2_range[2];
-  double loop1_var2_range[2];
-  double loop2_var2_range[2];
-
-  int sweep_var2_dac;
-  int loop1_var2_dac;
-  int loop2_var2_dac;
-
-  char sweep_var2_name[256];
-  char loop1_var2_name[256];
-  char loop2_var2_name[256];
-
-  parse_var2_comments(comments, "Sweep var2", &sweep_var2_dac, sweep_var2_name, sweep_var2_range);
-  parse_var2_comments(comments, "Loop 1 var2", &loop1_var2_dac, loop1_var2_name, loop1_var2_range);
-  parse_var2_comments(comments, "Loop 2 var2", &loop2_var2_dac, loop2_var2_name, loop2_var2_range);
-
-  char buf[256];
-  string sweep_extra = "";
-  if (sweep_var2_dac != 0)
-    {
-      snprintf(buf, 256, "%.3f to %.3f", sweep_var2_range[0], sweep_var2_range[1]);
-      sweep_extra = sweep_extra + " and " + sweep_var2_name + " from " + buf;
-    }
-
-  string loop1_extra = "";
-  if (loop1_var2_dac != 0)
-    {
-      snprintf(buf, 256, "%.3g to %.3g", loop1_var2_range[0], loop1_var2_range[1]);
-      loop1_extra = loop1_extra + " and " + loop1_var2_name + " from " + buf;
-    }
-
-  string loop2_extra = "";
-  if (loop2_var2_dac != 0)
-    {
-      snprintf(buf, 256, "%.3g to %.3g", loop2_var2_range[0], loop2_var2_range[1]);
-      loop2_extra = loop2_extra + " and " + loop2_var2_name + " from " + buf;
-    }
-      
-
-  string tmp;
-    if (delft_raw_units)
-    tmp = " (raw mV)";
-  else
-    tmp = " (mV)";
-
-  //if (delft_settings)
-  get_settings(comments);
-
-  if (!columns)
-    {
-      axisname[0] = sweep_name;
-      axisname[0].append(tmp);
-      axisname[0] += sweep_extra;
-      axisname[1] = loop1_name;
-      axisname[1].append(tmp);
-      axisname[1] += loop1_extra;
-      axisname[2] = loop2_name;
-      axisname[2].append(tmp);
-      axisname[2] += loop2_extra;
-      
-
-      // set the sweep range
-      axismin[0] = sweep_range[0];
-      axismax[0] = sweep_range[1];
-
-      // flip is now done correctly in load_mtx_cut, so we no longer need to flip...
-      axismin[1] = loop1_range[0];
-      axismax[1] = loop1_range[1];
-
-      // this one is fine.
-      axismin[2] = loop2_range[0];
-      axismax[2] = loop2_range[1];
-    }
-
-  else 
-    {
-      axisname[0] = "Column Number";
-      axismin[0] = 1;
-      axismax[0] = size[0] + 1;
-      
-      axisname[1] = sweep_name;
-      axisname[1].append(tmp);
-      axisname[1] += sweep_extra;
-
-      axismin[1] = sweep_range[0];
-      axismax[1] = sweep_range[1];
-      
-      // Check for unfinished loop
-      if (loop1_steps != size[2])
-       {
-         //info("loop1 %f %f steps %d size %d\n", loop1_range[0],
-         //loop1_range[1], loop1_steps, size[2]);
-              
-         double tmp  = loop1_range[0] 
-           + (loop1_range[1] - loop1_range[0])
-           * 1.0*size[2]/loop1_steps;
-         //info("Found incomplete loop: %d vs %d steps\n"
-         //"Adjusting endpoint from %e to %e\n",
-         //size[2], loop1_steps, loop1_range[1], tmp);
-         loop1_range[1] = tmp;
-       }
-      
-      axisname[2] = loop1_name;
-      axisname[2].append(tmp);
-      axisname[2] += loop1_extra;
-
-      // Note: here we need to flip loop 1 endpoints
-      // flip is now done correctly in load_mtx_cut, so we no longer need to flip...
-      axismin[2] = loop1_range[0];
-      axismax[2] = loop1_range[1];
-    }
-
-  // 
-  // A reasonable default... :)
-  dataname = "Current (pA)"; 
-  if (delft_settings)
-    dataname += settings;
-} 
-
-int nextline(FILE *fp, char *buf)
-{
-  if (fgets(buf, LINESIZE, fp) == NULL) 
-    return -1;
-  while (buf[0] == '#')
-    if (fgets(buf, LINESIZE, fp) == NULL) 
-      return -1;
-  //info(buf);
-  return 0;
-}
-
-double nextreading(FILE *fp, int col, int &lnum)
-{
-  //info("in next reading\n");
-  //getchar();
-  // char *buf = new char [LINESIZE]; doesn't work under windows? c++ runtime error?
-  char *buf = malloc(LINESIZE*sizeof(char));
-  double val;
-  char *p;
-
-  // Find the next line
-  while (1)
-    {
-      lnum++;
-      if (fgets(buf, LINESIZE, fp) == NULL) 
-       {
-         val = NAN;
-         break;
-       }
-      // Strip whitespace
-      for(p = buf; *p != 0 && isspace(*p); p++);
-      //Ignore comments or empty lines
-      if (*p == '#' || *p == '\n' || *p == '\r' || *p == 0)
-       continue;
-      val =  parse_reading(buf, col);
-      break;
-    }
-
-  free(buf);
-  return val;
-}
-
-double parse_reading(char *line, int col)
-{
-  char sep[] = " \t\n\r";
-  double val;
-  int i;
-  char *p; 
-  char *buf = strdup(line);
-  
-  // Now try to read the data
-  p = strtok(buf, sep);
-  for (i=0; i < col; i++) 
-    if (p != NULL) p = strtok(0,sep);
-  if (p == NULL) 
-    {
-      info("trouble parsing row for column %d:\n%s", col, line);
-      val = NAN;
-    }
-  //info("reading: %s\n", p);
-  else if (sscanf(p, "%lf", &val) != 1)  
-    {
-      info("trouble converting column value _%s_ to a float", p);
-      val = NAN;
-    }
-  free(buf);
-  return val; 
-} 
-
-
-int MTX_Data::load_dat_meta(const char *name, int col)
-{
-  info("read %s col %d\n", name, col);
-  char *buf = new char [LINESIZE];
-
-  // First open the metadata file and get the stuff we need.
-  string metafile = name;
-  metafile = search_replace(metafile, ".dat", ".meta.txt");
-  FILE *fp = fopen(metafile.c_str(), "r");
-  if (fp == NULL) return -1;
-
-  // First stuff should be the axis info
-  for (int i=0; i<3; i++)
-    {
-      if (nextline(fp, buf) == -1) return -1;
-      if (sscanf(buf, "%d", &size[i]) != 1) return -1;
-      if (nextline(fp, buf) == -1) return -1;
-      if (sscanf(buf, "%lf", &axismin[i]) != 1) return -1;
-      if (nextline(fp, buf) == -1) return -1;
-      if (sscanf(buf, "%lf", &axismax[i]) != 1) return -1;
-      if (nextline(fp, buf) == -1) return -1;
-      axisname[i] = buf; strip_newlines(axisname[i]);
-    }
-
-  // a recurring theme in spyview: we need to flip the y axis range...
-
-  // 19 July 2011: testing now with a file from Vincent, it seems we
-  // don't need to flip the y axis?  
-
-  // Actually, it is handier if we do flip the y axis, otherwise we
-  // need to flip the data afterwards for a conventional sweep.
-
-  double tmp = axismin[1];
-  axismin[1] = axismax[1];
-  axismax[1] = tmp;
-
-  // The next lines in the metadata file should be the (optional)
-  // column names. Start with a default label based on the column
-  // number, then replace it if we find a specific column label in the
-  // file.
-  dataname = str_printf("Column %d", col+1); //Note: column number starts at zero in c...
-  while (1)
-    {
-      int c;
-      if (nextline(fp, buf) == -1) break;
-      if (sscanf(buf, "%d", &c) != 1) break;
-      c--;
-      if (nextline(fp, buf) == -1) break;
-      if (c == col)
-       {
-         dataname = buf;
-         strip_newlines(dataname);
-       }
-    }
-  //info("dlab _%s_\n", dataname.c_str());
-  fclose(fp);
-
-  // Ok, now reading the .dat file should be pretty easy.
-
-  clear();
-  data = new double [size[0]*size[1]*size[2]]; 
-  data_loaded = 1;
-  fp = fopen(name, "r");
-  if (fp == NULL) return -2;
-
-  bool progress = (size[0]*size[1]*size[2]) > 100*100*100*5;
-  static char msgbuf[256];
-  if (progress && progress_gui)
-    {
-      open_progress_gui();
-      msg->value("Reading file: 0%");
-    }
-
-  double val, last_val;
-  val = last_val = 0;
-  int lnum = 0; // line number
-  int npoints = 0;
-  bool incomplete = false;
-
-  int i,j,k;
-  int i0, j0, k0;
-
-  // In test file from Vincent, the meta.txt code is getting the wrong order?
-  // for (k=0; k<size[2]; k++)
-  //   {
-  //     for (j=0; j<size[1]; j++)
-  //   {
-  //     for (i=0; i<size[0]; i++)
-  //       {
-  for (i=0; i<size[0]; i++)
-    {
-      for (j=size[1]-1; j>=0; j--) // flip y data around in matrix...
-       {
-         for (k=0; k<size[2]; k++)
-           {
-             if (incomplete) // fill matrix
-               getData(i,j,k) = last_val;
-             else // otherwise try to get new data
-               {
-                 val = nextreading(fp, col, lnum);
-                 if (isnan(val)) // failed to read a point
-                   {
-                     if (npoints == 0) 
-                       {
-                         info("could not read any points\nassuming empty file, filling with zeros\n");
-                         last_val = 0;
-                         getData(i,j,k) = last_val;
-                         incomplete = true;
-                       }
-                     else
-                       {
-                         info("Failed to find point number %d from line number %d, i,j,k = %d %d %d.\n"
-                              "Assuming incomplete file\n"
-                              "filling matrix with last reading %e\n", npoints, lnum, i, j, k, last_val);
-                         incomplete = true;
-                         getData(i,j,k) = last_val;
-                       }
-                   }
-                 else // add the new data to the matrix
-                   {
-                     getData(i,j,k) = val;
-                     last_val = val;
-                     npoints++;
-                   }
-               }
-           }
-         if (!incomplete && npoints % 1000 == 0)  // update progress gui
-           {
-             if (progress_gui)
-               Fl::check();
-             if (progress)
-               {
-                 snprintf(msgbuf,sizeof(msgbuf), "Reading File: %.0f%%", 1.0*k/(size[2]-1)*100.0);
-                 if (progress_gui)
-                   msg->value(msgbuf);
-                 else 
-                   info("%s\r", msgbuf);
-               }
-           }
-       }
-    }
-  fclose(fp);
-  return 0;
-}
diff --git a/spyview/ImageData.H.~1.56.~ b/spyview/ImageData.H.~1.56.~
deleted file mode 100644 (file)
index 56b18f8..0000000
+++ /dev/null
@@ -1,480 +0,0 @@
-#ifndef ImageData_H
-#define ImageData_H
-
-#include <FL/Fl_Double_Window.H>
-#include <FL/Fl_Output.H>
-
-#include <string>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <vector>
-#include <math.h>
-#include "message.h"
-
-#define QUANT_MAX 65535
-
-// Checking array limits will help debugging but will increase the
-// execution time. I have benchmarked this by calling load_file() on a
-// 1x801x601 mtx (which load the YZ cut by default), and then
-// reloading the YZ cut. Without limit checking, the excution time as
-// 0.299s. With limit checking, it was 0.370s.
-
-#define CHECK_ARRAY_LIMITS 0
-
-using namespace std;
-
-typedef enum { YZ = 0, XY = 2, XZ = 1 }  mtxcut_t;
-typedef enum { COLUMNS = 0, INDEX = 1}  gpload_t;
-typedef enum { DROP = 'd', FILL_MEAN = 'm', FILL_ZERO = 'z', EXIT = 'x', COPY_ADJACENT = 'a'} incorrect_column_t;
-typedef enum { MATRIX = 0, GNUPLOT = 1, DELFT_LEGACY = 2, DAT_META = 3}  datfile_t;
-typedef enum { PGM = 0, MTX = 1, DAT = 2}  fallbackfile_t;
-
-class MTX_Data
-{
-
-public:
-
-  string filename; 
-  double *data;
-  string axisname[3];
-  string dataname;
-  int size[3];
-  double axismin[3];  // the ranges for the x, y, and z axes
-  double axismax[3];  // the ranges for the x, y, and z axes
-  bool data_loaded;
-  bool data3d;
-  bool parse_txt;
-  bool delft_raw_units;
-  bool progress_gui;
-  bool delft_settings;
-
-  string settings;
-
-  MTX_Data();
-  ~MTX_Data();
-  
-  int load_file(const char *name);
-  int load_gp_index(const char *name, int col);
-  int load_gp_cols(const char *name);
-  int load_dat_meta(const char *name, int col);
-  void parse_delft_txt(const char *name, bool columns);
-  void parse_comments(char *comments, const char *ident, int *dac, int *size, char *name, double *range);
-  void parse_var2_comments(char *comments, const char *ident, int *dac, char *name, double *range);
-  void get_settings(const char *name);
-  
-  inline double get_coordinate(int axis, int i)
-  { 
-    axis = axis%3;
-    if (size[axis] == 1)
-      return (axismin[axis]+axismax[axis])/2.0;
-    else
-      return axismin[axis] + 1.0*i*(axismax[axis]-axismin[axis])/(size[axis]-1); 
-      //return axismin[axis] + 1.0*i*(axismax[axis]-axismin[axis])/(size[axis]); // why not minus one? 
-  };
-
-  inline double &getData(int i, int j, int k) 
-  {
-#if CHECK_ARRAY_LIMITS
-    if (!data_loaded)
-      { fprintf(stderr, "MTX data not yet loaded!\n"); exit(-1);}
-    if (i>=size[0] || i < 0)
-      { fprintf(stderr, "attempt to access i = %d, size[0] = %d\n", i, size[0]); exit(-1);}
-    if (j>=size[1] || j < 0)
-      { fprintf(stderr, "attempt to access j = %d, size[1] = %d\n", j, size[1]); exit(-1);}
-    if (k>=size[2] || k < 0)
-      { fprintf(stderr, "attempt to access k = %d, size[2] = %d\n", k, size[2]); exit(-1);}
-#endif 
-    return data[k*size[1]*size[0] + j*size[0] + i]; 
-  };
-  void clear() { if (data_loaded) delete [] data; data_loaded = 0;};
-
-  void open_progress_gui();
-  void close_progress_gui();
-
-  Fl_Double_Window *win;
-  Fl_Output *msg;
-  
-private: 
-};
-
-class ImageData 
-{
-
-public:
-
-  double *orig_data;
-  double *raw_data;
-  int *quant_data;
-  int width, height;
-  bool *threshold_reject;
-
-  MTX_Data mtx;
-
-  // Keep track of which mtx index and gp column are loaded
-  mtxcut_t mtx_cut_type;
-  int mtx_index; 
-  bool do_mtx_cut_title; 
-  gpload_t gpload_type; 
-  int gp_column;
-
-  bool auto_quant; 
-  double auto_quant_percent;
-
-  bool data_loaded;  
-  bool data3d;
-
-  datfile_t datfile_type;
-  fallbackfile_t fallbackfile_type;
-
-
-  double rawmin, rawmax;  // the actual min and max of the raw dataset
-  double qmin, qmax; // the raw values corresponding to 0 and QUANT_MAX
-  double xmin, xmax; // the values of i=0 and i=width-1
-  double ymin, ymax; // the values of j=0 and j=height-1
-  
-  string xname;
-  string yname;
-  string zname;
-
-  // We need to keep track of the orignal stuff for the reset() function
-  int orig_width, orig_height;
-  double orig_xmin;
-  double orig_xmax;
-  double orig_ymin;
-  double orig_ymax;
-  string orig_xname;
-  string orig_yname;
-
-  // Action on incorrect number of columns when reading DAT files
-  incorrect_column_t incorrect_column;
-
-  // Constructor will not do much by default
-  ImageData();
-  ~ImageData();
-
-  // Functions for loading new data
-
-  // Copy data from an existing fp matrix 
-  void load_raw(double *data, 
-               int w, int h,
-               double x1=NAN, double x2=NAN, 
-               double y1=NAN, double y2=NAN);
-
-  // Copy data from an existing int matrix
-  void load_int(int *data, 
-               int w, int h, 
-               double x1=NAN, double x2=NAN, 
-               double y1=NAN, double y2=NAN, 
-               double z1=NAN, double z2=NAN);
-  // Reset the data back to the original (for reprocesing data without
-  // reloading from file)
-  void reset();
-
-  // Memory allocation
-  void clear();
-  // reallocated space for arrays according to current width and height
-  // this is used when we load new data (will clear all arrays)
-  void reallocate(); 
-
-  // So far, we've tried to keep memory allocation to a minimum.  This
-  // has worked so far because all of the image processing stuff that
-  // changes the size of the datasets _shrink_ the dataset.  However,
-  // with the introduction of the interpolate function, we'll also
-  // need to make the storage arrays (like quant_data,
-  // threshold_reject) bigger. This is what this function does (note
-  // that it will never reallocate them smaller since we need to be
-  // able to restore the original data). We will leave the work of
-  // allocating raw_data to the image processing function.
-  void resize_tmp_arrays(int new_width, int new_height); 
-
-
-  // Many different functions will support threasholding Using this
-  // function, and the threshold_reject array, we will unify all of
-  // these to keep them consistent. It will also simplify the other
-  // code.
-
-  // Type: 0 = whole image, 1 = line, 2 = column, 3 = data value
-  void calculate_thresholds(int type, double low, double high, 
-                           double bottom_limit=-INFINITY, double top_limit=INFINITY);
-  
-  // Generic Load from file (determine filetype from extension)
-  // Programs using the this class can either use this function
-  // directly, but can also use the helper function directly
-  // 
-  // All load functions will return -1 if the file was not succesfully
-  // loaded.
-  int load_file(const char *name);
-
-  // Helpers to load data from specific files
-  int load_STM(const char *name);
-  int load_PGM(const char *name);
-  int load_DAT(const char *name);
-  int load_XL30S_TIF(const char *name); // hacked to read TIF files from XL30S
-  int load_Delft(const char *name);
-  // For the following functions, user should set the desired
-  // mtx_cut_type, mtx_index, gpload_type and gp_column. If they
-  // change during load (for example if they are out of range), then
-  // the variables in the class will store the correct value. 
-  // Alternatively, you can use the inline functions below
-  int load_MTX(const char *name);
-  int load_GP(const char *name);
-  // A new function that loads data from a "columns" formatted data
-  // file with the help of a new metadata file. The metadata file will
-  // be called "file.meta.txt". It will use gp_column number to pick
-  // the column. It will load 3D data into an MTX. 
-  int load_DAT_meta(const char *name);
-  void load_mtx_cut();
-  void saveMTX(const char *name); // Write the current image data to an MTX file
-
-  // Some handy functions:
-
-  inline int limit(int A) { if (A<0) return 0; else if (A>QUANT_MAX) return QUANT_MAX; else return A; };
-
-  inline int raw_to_quant(double raw) {return limit((int)round(1.0*(raw-qmin)*QUANT_MAX/(qmax-qmin)));}
-  inline double quant_to_raw(double quant) {return qmin + 1.0*quant*(qmax-qmin)/QUANT_MAX;};
-
-  // Given a pixel coordinate x, return the united coordinate.
-  inline double getX(double i) {return xmin + ((width==1) ? 0 : 1.0*i*(xmax-xmin)/(width-1));};
-  inline double getY(double j) {return ymin + ((height==1) ? 0 : 1.0*(height-1-j)*(ymax-ymin)/(height-1));}; // ymax is flipped
-
-  // Given a united coordinate x, return the un-united.
-  inline double getX_inv(double x, double zoom=1.0) { return (width==1) ? 0 : (zoom*(x-xmin)/(xmax-xmin)*(width-1)); }
-  inline double getY_inv(double y, double zoom=1.0) { return (height==1) ? 0 : zoom*(height-1-(y-ymin)/(ymax-ymin)*(height-1)); }
-  inline double getX_inv(double x, int zoom) { return (width==1) ? 0 : ((zoom > 0 ? zoom : -1.0/zoom)*(x-xmin)/(xmax-xmin)*(width-1)); }
-  inline double getY_inv(double y, int zoom) { return (height==1) ? 0 : (zoom > 0 ? zoom : -1.0/zoom)*(height-1-(y-ymin)/(ymax-ymin)*(height-1)); }
-
-  // This will rescale the floating point making the old qmin and qmax
-  // into the new qmin and qmax. This is the equivalent of changing
-  // the zunit settings in the old setup.
-
-  void rescale_data(double new_qmin, double new_qmax); 
-
-  // More convenient functions
-
-  inline void load_mtx_cut(int index) 
-  {mtx_index = index; load_mtx_cut();};
-  inline void load_mtx_cut(int index, mtxcut_t type) 
-  {mtx_index = index; mtx_cut_type = type; load_mtx_cut();};
-
-  inline void load_GP_cols(const char *name) 
-  {gpload_type = COLUMNS; load_GP(name);}
-  inline void load_GP_index(const char *name, int colnum) 
-  {gpload_type = INDEX; gp_column = colnum; load_GP(name);}
-  
-
-  // Copy original data back into raw data matrix (saves reloading from file)
-  inline void reload_orig() { memcpy(raw_data, orig_data, width*height*sizeof(double)); }
-
-  // Quantizing the data
-  void quantize();
-
-  // Image Processing Operations on data:
-
-  // Even simpler (inline) functions
-
-  inline void scale_axes(double xscale, double yscale)
-  {
-    //info("scale %e %e %e %e %e %e\n", xmin, xmax, ymin, ymax, xscale, yscale);
-    xmin *= xscale;
-    xmax *= xscale;
-    ymin *= yscale;
-    ymax *= yscale;
-    //info("scale %e %e %e %e\n", xmin, xmax, ymin, ymax);
-  }
-
-  inline void offset_axes(double xoff, double yoff)
-  {
-    info("off %e %e %e %e %e %e\n", xmin, xmax, ymin, ymax, xoff, yoff);
-    xmin += xoff;
-    xmax += xoff;
-    ymin += yoff;
-    ymax += yoff;
-    info("off %e %e %e %e\n", xmin, xmax, ymin, ymax);
-  }
-
-  // Very simple functions (one liners)
-  
-  void log10(bool do_offset, double new_offset);// data[i] = log10(data[i]) for all i  
-  void magnitude();// data[i] = abs(data[i]) for all i, !using z unit!
-  void neg();// data[i] = -(data[i]) for all i, !using z unit!
-  void offset(double offset, bool do_auto);// add an offset
-  void scale(double factor); // scale the data
-  void gamma(double gamma, double epsilon); // gamma scaling operation on 16 bit data
-
-  // More complicated functions that preserve the images size
-
-  void lbl(double bp=0.0, double tp=0.0, bool whole_image_threashold=false, bool percentiles=true, 
-          double bottom_limit = -INFINITY, double top_limit = INFINITY); // subtract line average from each line
-  void cbc(double bp=0.0, double tp=0.0, bool whole_image_threashold=false, bool percentiles=true,
-          double bottom_limit = -INFINITY, double top_limit = INFINITY); // subtract column average from each column
-  void sub_linecut(bool horizontal, int pos); // Subtract a specific line form each line.  
-  void outlier_line(bool horizontal, int pos); // Remove an outlier line
-  void norm_lbl(); // Normalize each line individually.  
-  void norm_cbc(); // Normalize each line individually.
-  void fitplane(double bp=0, double tp=0, bool percentiles=true); // subtract a plane
-  void plane(double b, double a); // subtract a plane
-  void xflip();   
-  void yflip();
-  void rotate_cw();
-  void rotate_ccw();
-  void grad_mag(double bias); // Replace each pixel with the magnitude of the gradient.  0<bias<1 biases one derv. as more important than the other.
-  void dderv(double theta); // Derivative along axis theta *degrees* off the x-axis.
-  void shift_data(int after_row, int offset); //designed for gate shifts
-
-  // look for "switches": Run across each row of the data: if the data
-  // changes by more than "threshold" in one pixel, then we consider
-  // this a switch. We the calculate an average over "avgwin" pixels
-  // before the switch, we add the difference to a running offset
-  // value that we add to all subsequent datapoints in the row.
-  void switch_finder(double threshold, int avgwin, bool vert); 
-
-
-  typedef enum { LOWPASS_GAUSS = 0, LOWPASS_LORENTZ = 1, LOWPASS_EXP = 2 , LOWPASS_THERMAL} lowpass_kernel_t;  void make_lowpass_kernel(double *data, double sigma, int size, lowpass_kernel_t type=LOWPASS_GAUSS);
-  void lowpass(double xsize, double ysize, lowpass_kernel_t type, double mult=7.0); // width is width of mask to use measured in units of xsize, ysize. FWHM is 2.35, so around 6 works well.
-  void highpass(double xsize, double ysize, double passthrough=0.0,lowpass_kernel_t type=LOWPASS_GAUSS, double mult=7.0); // mult is width of mask to use measured in units of xsize, ysize
-  void notch(double xlow, double xhigh, double ylow, double yhigh, double width=7.0); // width is width of mask to use measured in units of xsize, ysize
-  void equalize();  // Perform histogramic equalization
-
-  void despeckle(bool despeckle_x, bool despeckle_y);
-
-  void crop(int left, int right, int lower, int upper);
-
-  // Functions that change the image size. These are going to be tricky
-  // to deal with, especially since we also want to keep the original 
-  // data around!
-
-  // These functions will not shrink the size of the allocated data
-  // storage matrices as we want to be able to use reset() to reload
-  // the original data using memcpy. They may change the values of
-  // width and height, so that raw(i,j) retrieves the correct values
-
-  void pixel_average(int nx, int ny); // average adjacent pixels to downsample data
-  void xderv(); // take a horizontal derivative
-  void yderv(); // take a vertical derivative
-  void ederv(double pscale, double nscale); // take a vertical derivative, with sign flipped at y=0
-  void even_odd(bool even, bool fwd_rev); // extract either even or odd rows
-  void remove_lines(int start, int nlines); // remove lines, vertically shifting the data and adjusting the ymax
-  void interpolate(int new_width, int new_height, int type=0); // regrid the data, using bilinear interpolation (maybe bicubic in the future)
-  inline void scale_image(double xs, double ys) // an obvious next step...
-  { interpolate(width*xs, height*ys); };
-
-  void hist2d(double dmin, double dmax, int num_bins); //Transform the y-axis data in to a 2D histogram of datavalues
-
-  // Functions for accessing the data with an (i,j) syntax (like
-  // Oliver's pixel() function in Image2D) (what does the second one
-  // with the const do?)  
-
-  // I've also added array bounds checking, which may slow it down (?)
-  // but should help catch loads of bugs.
-
-  inline double &raw(int i, int j) 
-  {
- #if CHECK_ARRAY_LIMITS
-    if (!data_loaded) 
-      {fprintf(stderr, "Data not loaded!\n"); exit(-1);}
-    if (i >= width || i < 0)
-      {fprintf(stderr, "attempt to acces i = %d, width = %d\n", i, width); return raw_data[0];}
-    if (j >= height || j < 0)
-      {fprintf(stderr, "attempt to acces j = %d, height = %d\n", i, height); return raw_data[0];}
-#endif
-    return raw_data[j*width+i];
-  }; 
-
-  inline const double &raw(int i, int j) const 
-  {
- #if CHECK_ARRAY_LIMITS
-    if (!data_loaded) 
-      {fprintf(stderr, "Data not loaded!\n"); exit(-1);}
-    if (i >= width || i < 0)
-      {fprintf(stderr, "attempt to acces i = %d, width = %d\n", i, width); exit(-1);}
-    if (j >= height || j < 0)
-      {fprintf(stderr, "attempt to acces j = %d, height = %d\n", i, height); exit(-1);}
-#endif
-    return raw_data[j*width+i];
-  }; 
-
-  inline int &quant(int i, int j) 
-  {
- #if CHECK_ARRAY_LIMITS
-    if (!data_loaded) 
-      {fprintf(stderr, "Data not loaded!\n"); exit(-1);}
-    if (i >= width || i < 0)
-      {fprintf(stderr, "attempt to acces i = %d, width = %d\n", i, width); exit(-1);}
-    if (j >= height || j < 0)
-      {fprintf(stderr, "attempt to acces j = %d, height = %d\n", i, height); exit(-1);}
-#endif
-    return quant_data[j*width+i];
-  }; 
-
-
-  // How cool an idea is this?
-  //
-  // Eventually, use bicubic interpolation for the pixels in the middle:
-  //
-  // http://www.paulinternet.nl/?page=bicubic
-  //
-  // but then bilinear interpolation for ones at the edges. 
-  //
-  // Start by just using bilinear everywhere...the add the bicubic later. (maybe)
-
-  inline double raw_interp(double x, double y)
-  {
-    int i = (int)floor(x);
-    int j = (int)floor(y);
-
-    if (i<0 || i > width-1 || j < 0 || j > height-1)
-      {
-       info("interp outside dataset: %e (%d) %e (%d)\n", x, width-1, y, height-1);
-       return NAN;
-      }
-    
-    double dx = x-(double)i;
-    double dy = y-(double)j;
-
-    // The boundary corner
-    if (i == width-1 && j == height-1)
-      return raw(i,j);
-    
-    // The right edge
-    if (i == width-1)
-      return raw(i,j) + (raw(i,j+1)-raw(i,j))*dy;
-    
-    // The bottom edge
-    if (j == height-1)
-      return raw(i,j) + (raw(i+1,j)-raw(i,j))*dx;
-
-    
-    // The rest (from wikipedia)
-    return 
-      ((raw(i,j)) + //b1
-      (raw(i+1,j)-raw(i,j))*dx + // b2*x
-      (raw(i,j+1)-raw(i,j))*dy + // b3*y
-      (raw(i,j)-raw(i+1,j)-raw(i,j+1)+raw(i+1,j+1))*dx*dy); // b4*x*y
-  };
-    
-private:
-
-  // Some internal functions
-  int parse_pgm_comments(const char *ident, const char *fmt, void *val, char *p, const char *filename);
-
-  inline int check_loaded() {
-  if (data_loaded == 0)
-    {
-      fprintf(stderr, "data accessed before loading! exiting...\n");
-      exit(-1);
-    }
-  }    
-  
-  void find_raw_limits(); // find the min/max of the raw data: we 
-
-  void find_threasholds(vector <double> data, 
-                       double bottom_percent, double top_percent,
-                       double &low, double &high);
-  void find_image_threasholds(double bottom_percent, double top_percent,
-                             double &low, double &high);
-  void store_orig();
-};
-
-
-#endif
diff --git a/spyview/ImagePrinter.C.~1.104.~ b/spyview/ImagePrinter.C.~1.104.~
deleted file mode 100644 (file)
index 4c2a3db..0000000
+++ /dev/null
@@ -1,1778 +0,0 @@
-#include <sys/types.h>
-#include "ImagePrinter.H"
-#include "ImageWindow.H"
-#include "ImageWindow_LineDraw.H"
-#include "message.h"
-#include "throttle.H"
-#include <algorithm>
-#include <sys/time.h>
-#include "eng.h"
-#include <limits.h>
-#include <libgen.h>
-
-// Violating all rules of abstraction, but I can't figure our any other way to get access to argv[0]
-#include "spyview.H"
-
-static bool Clip(double &x1,double &y1,double &x2,double &y2, double wx1, double wy1, double wx2, double wy2);
-static void setColor(FILE *out, Fl_Color_Chooser *c);
-
-#ifndef WIN32
-#include <sys/wait.h>
-using namespace boost;
-using namespace serialization;
-using namespace std;
-#endif 
-
-static const double INCH=72.0; // Inch in points.
-using namespace std;
-std::string Image_Printer::settingsDir;
-
-// Implementation of cohen-sutherland algorithm.
-static const int NONE=0;
-static const int LEFT=1;
-static const int RIGHT=2;
-static const int TOP=4;
-static const int BOTTOM=8;
-
-int wx1,wy1,wx2,wy2;
-
-Image_Printer::Image_Printer(ImageWindow *p_iw, Image_Printer_Control *p_ipc)
-{
-  iw = p_iw;
-  ipc = p_ipc;
-  ipc->ip = this;
-  ipc->face->value("Palatino");
-  ipc->fontsize->value("24");
-  width=7;
-  ipc->height->value("7.0");
-  xoff=1;
-  yoff=1;
-  boxwidth=4;
-  tickwidth=4;
-  ticklength=.25;    
-  zero=1e-15;
-  xspacing=0;
-  yspacing=0;
-  ipc->xscale->value("1.0");
-  ipc->yscale->value("1.0");
-  ipc->zscale->value("1.0");
-
-  ipc->xticfmt->value("%.2g");
-  ipc->yticfmt->value("%.2g");
-  ipc->cticfmt->value("%.2g");
-  page_width = 11;
-  page_height = 8.5;
-  ipc->landscape->value(1);
-  ipc->colorbar->value(0);
-  loadPrintSettings(""); // Load the default settings...
-  previewFileName = tmpnam(NULL);  
-  previewProc = -1;
-
-  // Some default settings for the preview & formats, in case the
-  // settings file is not found
-  ipc->png_dpi->value("300");
-#ifdef WIN32
-  ipc->gs_cmd->value("\"c:/Program Files/gs/gs8.64/gswin32c.exe\"");
-  ipc->preview_cmd->value("\"c:/Programs Files/Ghostgum/gsview/gsview32.exe\"");
-#else
-  ipc->gs_cmd->value("gs");
-  ipc->preview_cmd->value("gv --watch");
-#endif
-  loadPreviewSettings();
-}
-
-Image_Printer::~Image_Printer()
-{
-  info("Cleaning up\n");
-
-#ifndef WIN32
-  if(previewProc != -1) // We're about to unlink the preview ps file.  Better kill gs first.
-    kill(previewProc,SIGTERM);
-#endif
-
-  unlink(previewFileName.c_str());
-}
-
-void Image_Printer::do_extra_conversions(string basename)
-{
-  string command = "";
-  if (ipc->extra_pdf->value())
-    {
-      command = "";
-      command = ipc->gs_cmd->value();
-      if (ipc->cmyk->value())
-       command += " -dProcessColorModel=/DeviceCMYK ";
-      if (ipc->paper_letter->value())
-       command += " -sPAPERSIZE=letter ";
-      else if (ipc->paper_a4->value())
-       command += " -sPAPERSIZE=a4 ";
-      command += " -q -sDEVICE=pdfwrite -dBATCH -dNOPAUSE -dEPSCrop ";
-      command += " -dAutoFilterColorImages=false -dAutoFilterGrayImages=false ";
-      command += " -dColorImageFilter=/FlateEncode -dGrayImageFilter=/FlateEncode ";
-      command += " -sOutputFile=\"" + basename + ".pdf\" \"";
-      command += basename + ".ps\"";
-      info("pdf command:\n%s\n",command.c_str());
-      // Don't you just love win32? This is pretty obvious, right?
-      // http://jason.diamond.name/weblog/2005/04/14/dont-quote-me-on-this
-#ifdef WIN32
-      system(("\""+command+"\"").c_str());
-#else
-      system(command.c_str());
-#endif
-    }
-  if (ipc->extra_png->value())
-    {
-      command = "";
-      command = ipc->gs_cmd->value();
-      if (ipc->paper_letter->value())
-       command += " -sPAPERSIZE=letter ";
-      else if (ipc->paper_a4->value())
-       command += " -sPAPERSIZE=a4 ";
-      command += " -q -sDEVICE=pngalpha -dBATCH -dNOPAUSE -dEPSCrop ";
-      command += " -r";
-      command += ipc->png_dpi->value();
-      command += " -sOutputFile=\"" + basename + ".png\" \"";
-      command += basename + ".ps\"";
-      info("png command:\n%s\n",command.c_str());
-#ifdef WIN32
-      system(("\""+command+"\"").c_str());
-#else
-      system(command.c_str());
-#endif
-    }
-  if(ipc->extra_svs->value())
-    {
-      savesettings(basename + ".svs");
-    }
-
-  if(ipc->extra_set->value())
-    {
-      savePrintSettings(basename + ".set");
-    }
-  info("done\n");
-}
-
-void Image_Printer::startPreview()
-{
-#ifndef WIN32
-  if(previewProc != -1)
-    kill(previewProc,SIGTERM);
-#endif
-  updatePreview(true);
-#ifndef WIN32
-  previewProc = fork();
-#endif
-  if(previewProc == 0) // We're the baby
-    execlp("gv","gv",previewFileName.c_str(),"--watch", NULL);  
-}
-
-void Image_Printer::updatePreview(bool first)
-{
-  static Throttle<Image_Printer> throttle(this,&Image_Printer::updatePreview, 1.0);
-  if(!throttle.throttle())
-    return;
-  //reset_time();
-  //validatePreviewCmd();
-  if (previewFileName.size() == 0) return;
-  if(!first)
-    {
-      if(previewProc == -1)
-       return;
-      // If the viewer has quit, exit.         
-      int stat;                
-      int ret = 0;
-#ifndef WIN32
-      ret = waitpid(previewProc,&stat,WNOHANG);                
-#endif
-      if(ret != 0)             
-       {               
-         warn("PS viewer has quit...\n");              
-         previewProc = -1;             
-         unlink(previewFileName.c_str());
-         return;               
-       }
-    }
-  char *n = tmpnam(NULL);
-
-  FILE *out = fopen(n,"w");
-  print(out,true);
-  fclose(out);
-
-  //  printf("Took %g seconds to generate preview\n",current_time());
-  // No need to unlink the old file; rename is guaranteed to do that atomically.
-  //  if (unlink(previewFileName.c_str()) != 0)
-  //    info("error deleteing file \"%s\": %s\n", previewFileName.c_str(), strerror(errno));
-  if (rename(n,previewFileName.c_str()) != 0)
-    info("error renaming file \"%s\" to \"%s\": %s\n", n, previewFileName.c_str(), strerror(errno));
-#ifndef WIN32
-  if(!first)
-    kill(previewProc,SIGHUP);
-#endif
-}
-
-double Image_Printer::autospace(double min, double max)
-{
-  double range = fabs(min-max);
-  if(range*range == 0)
-    {
-      return 1;
-    }  
-  
-  double digitsRange = floor(log10(range));
-  double rangeMult = (double)pow(10.0,digitsRange);
-  
-  double collapsedRange = range/rangeMult;
-  if(collapsedRange < 2.5)
-    return .25 * rangeMult;
-  else if(collapsedRange < 5)
-    return .5 * rangeMult;
-  else if(collapsedRange <= 10)
-    return 1.0 * rangeMult;
-  warn("Tick Pick Problem... min %e max %e\n", min, max);
-  return 1.0 * rangeMult;
-}
-
-void Image_Printer::pixelToDevice(double &x, double &y)
-{
-  double xscale = atof(ipc->xscale->value());
-  double yscale = atof(ipc->yscale->value());
-  
-  y = iw->id.getY(y)*yscale; // Why the hell is this right?
-  // Why does spyview have so many coordinate systems, some of which have 0,0 as top-left, some as bottom-left?
-  x = iw->id.getX(x)*xscale;
-  unitToDevice(x,y);  
-}
-void Image_Printer::unitToDevice(double &x, double &y)
-{
-  double height = atof((ipc->height->value()));
-  double xscale = atof(ipc->xscale->value());
-  double yscale = atof(ipc->yscale->value());
-  double xmin = iw->id.getX(img_x1)*xscale;
-  double xmax = iw->id.getX(img_x2)*xscale;
-  double ymin = iw->id.getY(img_y1)*yscale;
-  double ymax = iw->id.getY(img_y2)*yscale;
-  
-  double xrange, xoffset, yrange, yoffset;
-  if (ipc->precise_ticks->value())
-    {
-      xrange=width*(img_xsize-1)/(img_xsize);  // xmin is actually 1/2 pixel from the left edge, xmax is 1/2 pixel from the right.
-      xoffset = width*(0.5/(img_xsize));
-      yrange = height*(img_ysize-1)/(img_ysize);
-      yoffset = height*(0.5/(img_ysize)); 
-    }
-  else 
-    {
-      yrange = height;
-      yoffset = 0;
-      xrange=width;
-      xoffset=0;
-    }
-  y = yoff + yrange*(y-ymax)/(ymin-ymax) + yoffset;
-  x = xoff + xrange*(x-xmin)/(xmax-xmin) + xoffset;
-}
-// void Image_Printer::validatePreviewCmd()
-// {
-//   if(strstr(ipc->preview_cmd->value(),".ps"))
-//     {
-//       warn("Overriding apparently inappropriate preview command \"%s\" with default of \"%s\"\n",
-//        ipc->preview_cmd->value(),defaultPreviewCmd);
-//       ipc->preview_cmd->value(defaultPreviewCmd);
-//     }
-// }
-
-void Image_Printer::box(FILE *out, double x, double y, double w, double h)
-{
-  fprintf(out,"     %g inch %g inch moveto\n",x,y);
-  fprintf(out,"     %g inch 0  rlineto\n",w);
-  fprintf(out,"     0 %g inch rlineto\n",h);
-  fprintf(out,"     %g inch 0 rlineto closepath\n",-w);
-}
-void Image_Printer::pushClip(FILE *out, double xoff, double yoff,double width,double height)
-{  
-  fprintf(out,"     clipsave\n");
-  box(out, xoff,yoff,width,height);
-  fprintf(out,"     clip\n");
-}
-
-/* This function is getting *way* too long and messy.  Something needs to be done.. */
-void Image_Printer::print(FILE *out_p, bool preview_p)
-{
-  preview = preview_p;
-  out = out_p;
-
-  // initialize some variables
-  computePlotRange();
-  max_ytic_width = 0; // for choosing the offset of the y axix label
-  max_ctic_width = 0; // for choosing the offset of the colorbar axix label
-  height = atof((ipc->height->value()));
-  fontsize = atof(ipc->fontsize->value());
-  xscale = atof(ipc->xscale->value());
-  yscale = atof(ipc->yscale->value());
-  zscale = atof(ipc->zscale->value());
-  
-  write_header();
-
-  if (ipc->landscape->value() && !ipc->paper_eps->value())
-    fprintf(out, "%d 0 translate 90 rotate\n", bb_ur_x );
-
-  if(ipc->watermark->value())
-    write_watermark();
-
-  draw_image();
-  draw_lines();
-
-  if (ipc->colorbar->value())
-    draw_colorbar();
-
-  draw_axis_tics();
-
-  // Draw the bounding box
-  if(boxwidth > 0)
-    {
-      fprintf(out,"%% Draw our box around the plot\n");
-      setColor(out,ipc->border_color);
-      fprintf(out,"  %g setlinewidth newpath\n",boxwidth);
-      box(out,xoff,yoff,width,height);
-      fprintf(out,"  stroke\n");
-    }
-  else
-    fprintf(out,"%% User requested no box\n");  
-
-  draw_axis_labels();
-
-  // By defering the bounding box, we now have access to max_ytic_width and max_ctic_width                             
-  if (ipc->paper_eps->value())
-    {
-      int label_x = static_cast<int>(- (max_ytic_width+2.5)*fontsize/2.0);
-      int label_c = static_cast<int>((max_ctic_width+2.5)*fontsize/2.0);
-      // Tricky part: estimate a nice bounding box for an EPS file
-      bb_ll_x = (int) (xoff*INCH - (ipc->yaxis_label->value() ? 1 : -1) * fontsize + label_x); 
-      // the y axis tickmark labels are much wider than the x axis are tall
-      bb_ll_y = (int) (yoff*INCH - (ipc->xaxis_label->value() ? 3 : 2) * fontsize);
-      if(ipc->colorbar->value())
-       bb_ur_x = (int) ((cbar_xoff+cbar_width)*INCH + label_c + (ipc->caxis_label->value() ? fontsize : 0));
-      else
-       bb_ur_x = (int) ((xoff+width)*INCH + fontsize);
-      bb_ur_y = (int) ((yoff+height)*INCH + (ipc->do_title->value() ? 2 : 1) * fontsize);
-    }
-
-  if (ipc->dir_stamp->value())
-    add_dirstamp();
-
-  if (preview || !ipc->paper_eps->value()) // If we're using eps, spec says no showpage (adobe maybe disagrees)
-    fprintf(out,"showpage\n");
-  fprintf(out,"grestore\n");
-  fprintf(out,"%%%%Trailer\n");
-  fprintf(out, "%%%%Actual BoundingBox was: %d %d %d %d\n", bb_ll_x, bb_ll_y, bb_ur_x, bb_ur_y); 
-  fprintf(out,"%%%%EOF\n");
-
-  info("Label width actual values:\n");
-  info("ytic %d ctic %d\n", max_ytic_width, max_ctic_width);
-  info("%%%%BoundingBox: %d %d %d %d\n", bb_ll_x, bb_ll_y, bb_ur_x, bb_ur_y); 
-}
-
-void Image_Printer::updatePlotRange(Image_Printer_Control *ipc)
-{
-  computePlotRange();
-  double xscale = atof(ipc->xscale->value());
-  double yscale = atof(ipc->yscale->value());
-
-  char buf[1024];
-  double minx, miny, maxx, maxy;
-  //int img_x1, img_y1, img_x2, img_y2; // overriding class variables!!!?
-  switch(ipc->plotRange->value())
-    {
-    case PLOT_ZOOM:
-      iw->zoom_window->getSourceArea(img_x1, img_y1, img_x2, img_y2);
-      //falling case!
-    case PLOT_MANUAL:
-      minx = iw->xunit(img_x1);
-      maxx = iw->xunit(img_x2);
-      miny = iw->yunit(img_y1-1); //strange: why did i need to -1?
-      maxy = iw->yunit(img_y2-1);      
-      break;
-    case PLOT_ALL:
-    default:
-      minx = iw->xunit(0);
-      maxx = iw->xunit(iw->w-1);
-      miny = iw->yunit(0);
-      maxy = iw->yunit(iw->h-1);
-      break;
-    }
-  minx *= xscale;
-  miny *= yscale;
-  maxx *= xscale;
-  maxy *= yscale;
-  snprintf(buf,sizeof(buf),"%g,%g",minx,maxx);
-  ipc->xrange->value(buf);
-  snprintf(buf,sizeof(buf),"%g,%g",maxy,miny);
-  ipc->yrange->value(buf);
-}
-
-void Image_Printer::computePlotRange()
-{
-  double xscale = atof(ipc->xscale->value());
-  double yscale = atof(ipc->yscale->value());
-
-  switch(ipc->plotRange->value())
-    {
-    case PLOT_ALL:
-    default:
-      img_x1 = 0; 
-      img_y1 = 0;
-      img_x2 = iw->w-1; 
-      img_y2 = iw->h-1;
-      break;
-    case PLOT_ZOOM:
-      if(iw->zoom_window)
-       iw->zoom_window->getSourceArea(img_x1, img_y1, img_x2, img_y2);
-      else
-       {
-         ipc->plotRange->value(PLOT_ALL);
-         computePlotRange();
-         return;
-       }
-      break;
-    case PLOT_MANUAL:
-      {
-       double xmin,xmax,ymin,ymax;
-       if(sscanf(ipc->xrange->value(),"%lg,%lg",&xmin,&xmax) == 2)
-         {
-           img_x1 = round(iw->id.getX_inv(xmin / xscale));
-           img_x2 = round(iw->id.getX_inv(xmax / xscale));
-           if(img_x1 > img_x2)
-             swap(img_x1,img_x2);
-         }
-       else
-         {
-           warn("Warning: X Range \"%s\" isn't of the form 1.0,2.0\n",ipc->xrange->value());
-           img_x1 = 0; 
-           img_x2 = iw->w-1; 
-         }
-       if(sscanf(ipc->yrange->value(),"%lg,%lg",&ymax,&ymin) == 2)
-         {
-           img_y1 = round(iw->id.getY_inv(ymin / yscale));
-           img_y2 = round(iw->id.getY_inv(ymax / yscale));
-           if(img_y1 > img_y2)
-             swap(img_y1,img_y2);
-         }
-       else
-         {
-           warn("Warning: Y Range \"%s\" isn't of the form 1.0,2.0\n",ipc->yrange->value());
-           img_y1 = 0; 
-           img_y2 = iw->h-1; 
-         }
-      }
-    }
-  img_xsize = abs(img_x2-img_x1+1);
-  img_ysize = abs(img_y2-img_y1+1);
-}
-
-void Image_Printer::updateSettings(Image_Printer_Control *ipc)
-{
-  char buf[64];
-
-  snprintf(buf,sizeof(buf),"%g",width);
-  ipc->width->value(buf);
-  snprintf(buf,sizeof(buf),"%g",xoff);
-  ipc->xoff->value(buf);
-  snprintf(buf,sizeof(buf),"%g",yoff);
-  ipc->yoff->value(buf);
-
-  snprintf(buf,sizeof(buf),"%g",ticklength);
-  ipc->ticklength->value(buf);
-  snprintf(buf,sizeof(buf),"%g",xspacing);
-  ipc->xspacing->value(buf);
-  snprintf(buf,sizeof(buf),"%g",yspacing);
-  ipc->yspacing->value(buf);
-
-  snprintf(buf,sizeof(buf),"%g",boxwidth);
-  ipc->boxwidth->value(buf);
-  snprintf(buf,sizeof(buf),"%g",tickwidth);
-  ipc->tickwidth->value(buf);  
-  updatePlotRange(ipc);
-  update_page_size();
-}
-
-void Image_Printer::fetchSettings(Image_Printer_Control *ipc)
-{
-  width=atof(ipc->width->value());
-  xoff=atof(ipc->xoff->value());
-  yoff=atof(ipc->yoff->value());
-
-  ticklength=atof(ipc->ticklength->value());
-  xspacing=atof(ipc->xspacing->value());
-  yspacing=atof(ipc->yspacing->value());
-
-  boxwidth=atof(ipc->boxwidth->value());
-  tickwidth=atof(ipc->tickwidth->value());
-
-  updatePreview();
-}
-
-void Image_Printer::update_page_size(int type)
-{
-  // This is a pain in the ass because in FLTK, the status of the
-  // other radio buttons is not updated until after the callback is
-  // executed: during the callback, two radio buttons could both be
-  // "1" at the same time...
-
-  if (type == -1 && ipc->paper_letter->value())
-    type = 1;
-  else if (type == -1 && ipc->paper_a4->value())
-    type = 2;
-
-  if (type == 1)
-    {
-      page_width = 8.5;
-      page_height = 11.0;
-    }
-
-  else if (type == 2)
-    {
-      page_width = 8.27;
-      page_height = 11.69;
-    }
-
-  if (ipc->landscape->value())
-    {
-      double tmp = page_width;
-      page_width = page_height;
-      page_height = tmp;
-    }
-}
-
-void Image_Printer::setAspectRatio(int change_axis)
-{
-  double target_width, target_height;
-  
-  double cur_height = atof(ipc->height->value());
-  double cur_width = width;
-  
-  // define ar as h/w, giving h = ar*w, w = h/ar
-  double spyview_ar = 1.0* iw->dozoom(iw->h, iw->yzoom) / iw->dozoom(iw->w, iw->xzoom);
-  
-  // change axis:
-  // 1 = change width, keep left edge
-  // 2 = change width, center
-  // 3 = change width, keep right edge
-  // 4 = change height, keep top edge
-  // 5 = change height, center
-  // 6 = change height, keep bottom edge
-
-
-  if (change_axis < 4) // change width
-    {
-      target_width = cur_height / spyview_ar;
-      target_height = cur_height;
-      if (change_axis == 2)
-       xoff += (cur_width - target_width)/2;
-      else if (change_axis == 3)
-       xoff += (cur_width - target_width);
-    }
-  else
-    {
-      target_width = cur_width;
-      target_height = cur_width * spyview_ar;
-      if (change_axis == 4)
-       yoff += (cur_height - target_height);
-      else if (change_axis == 5)
-       yoff += (cur_height - target_height)/2;
-    }
-
-  width = target_width;
-
-  //historically, height is not a local class variable...
-  char buf[1024];
-  snprintf(buf,sizeof(buf),"%g",target_height);
-  ipc->height->value(buf);
-  updateSettings(ipc);
-  //ipc->center_x->do_callback();
-  //ipc->center_y->do_callback();
-}
-
-static void maybe_mkdir(const char *name)
-{
-#ifdef WIN32
-  if(mkdir(name) == 0)
-#else
-    if(mkdir(name,0777) == 0)
-#endif
-  
-      switch(errno)
-       {
-       case EEXIST:
-         return;
-       default:
-         warn("Unable to create directory \"%s\": %s\n",name,strerror(errno));
-         return;
-       }
-}
-
-void Image_Printer::initSettingsDir()
-{
-  string buf;
-#ifdef WIN32
-  if(getenv("SPYVIEW_PREF_DIR") != NULL)
-    buf = getenv("SPYVIEW_PREF_DIR");
-  else
-    buf = sharedir;
-#else
-  buf = getenv("HOME");
-  buf = buf + DIRECTORY_SEPARATOR + ".spyview";
-#endif
-  maybe_mkdir(buf.c_str());
-  buf = buf + DIRECTORY_SEPARATOR + "print_settings";
-  settingsDir = buf;
-  maybe_mkdir(buf.c_str());
-}
-
-void Image_Printer::savePreviewSettings()
-{
-  string name;
-  initSettingsDir();
-  if(name.empty())
-    name = settingsDir + DIRECTORY_SEPARATOR + "settings.prv";
-
-  std::ofstream ofs(name.c_str());
-  boost::archive::text_oarchive ar(ofs);
-
-  int version;
-  ar & version;
-  // All this stuff is in version 1
-  ar & flcast(ipc->preview_cmd);
-  ar & flcast(ipc->gs_cmd);
-  ar & flcast(ipc->extra_pdf);
-  ar & flcast(ipc->extra_png);
-  ar & flcast(ipc->png_dpi);
-  ar & flcast(ipc->cmyk);
-}
-
-void Image_Printer::loadPreviewSettings()
-{
-  string name;
-  initSettingsDir();
-  if(name.empty())
-    name = settingsDir + DIRECTORY_SEPARATOR + "settings.prv";
-
-  std::ifstream ifs(name.c_str());
-  if (!ifs.good())
-    {
-      info("preview settings file _%s_ not found\n", name.c_str());
-      return;
-    }
-  boost::archive::text_iarchive ar(ifs);
-
-  int version;
-  ar & version;
-  ar & flcast(ipc->preview_cmd);
-  ar & flcast(ipc->gs_cmd);
-  ar & flcast(ipc->extra_pdf);
-  ar & flcast(ipc->extra_png);
-  ar & flcast(ipc->png_dpi);
-  ar & flcast(ipc->cmyk);
-}
-
-
-void Image_Printer::savePrintSettings(std::string name)
-{
-  fetchSettings(ipc); // Should be redundant, but paranoia is good.
-  initSettingsDir();
-  if(name.empty())
-    {
-      name = settingsDir + DIRECTORY_SEPARATOR + "default.set";
-    }
-
-  const char *fname = name.c_str();
-  std::ofstream ofs(fname);
-  try
-    {
-      if(!ofs.good())
-       throw(1);
-    }
-  catch (...)
-    {
-      warn("Unable to create or overwrite settings file \"%s\"\n",fname);
-    }
-  try
-    {
-      boost::archive::text_oarchive oa(ofs);
-
-      // For some reason, on WIN32 even have this code compiled into
-      // the program, even if it is not executed (!?), causes a
-      // crash.
-       
-      // Upon further inspection, this causes a crash on my machine
-      // at work, but not on my machine at home. Also, curiously, on
-      // my machine at work, the fltk widgets have now started to be
-      // displayed at unix "dark grey" instead of the usual windows
-      // "light biege". At home, where the exact same executable is
-      // not crashing, the fltk widgets are beige (except for the
-      // first warning dialog box!!!)
-
-      oa & (*this);
-    }
-  catch (boost::archive::archive_exception e)
-    {
-      error("ImagePrinter serialization error: %s",e.what());
-    }
-  catch (...)
-    {
-      error("Unknown serialization error\n");
-    }
-
-}
-
-void Image_Printer::loadPrintSettings(std::string name)
-{
-  initSettingsDir();
-  if(name.empty())
-    {
-      name = settingsDir + DIRECTORY_SEPARATOR + "default.set";
-    }
-  
-  const char *fname = name.c_str();
-  try 
-    {
-      std::ifstream ifs(fname);
-      if(!ifs.good())
-       throw(1);
-      boost::archive::text_iarchive ia(ifs);
-      ia & (*this);
-      updateSettings(ipc);
-    }
-  catch (boost::archive::archive_exception e)
-    {
-      error("Serialization error: %s",e.what());
-    }
-  catch (...)
-    {
-      warn("Unable to load settings file \"%s\": %s\n",fname,strerror(errno));
-    }
-}
-
-
-static inline int chGetCode(double x, double y, double wx1, double wy1, double wx2, double wy2)
-{
-  double eps = max(fabs(wx1-wx2),fabs(wy1-wy2))*1e-6;
-  int code = NONE;
-  if(x<wx1-eps) 
-    code |= LEFT;
-  else if(x>wx2+eps) 
-    code |= RIGHT; 
-  if(y<wy1-eps)
-    code |= TOP;
-  else if(y>wy2+eps)
-    code |= BOTTOM;
-  return code;
-}
-
-static inline bool SubClip(double &x1,double &y1,double &x2,double &y2, double wx1, double wy1, double wx2, double wy2)
-{
-  if(wy2 < wy1)
-    swap(wy2,wy1);
-  if(wx2 < wx1)
-    swap(wx2,wx1);
-  if(fabs(x2-x1) < fabs(y2 - y1))
-    return SubClip(y1,x1,y2,x2,wy1,wx1,wy2,wx2);
-  double m, tx, ty;
-  int code1, code2;
-  m=(y2-y1)/(float)(x2-x1);
-  code1=chGetCode(x1,y1,wx1,wy1,wx2,wy2);
-  code2=chGetCode(x2,y2,wx1,wy1,wx2,wy2);
-  for(int i = 0; i < 20; i++)
-    {
-      if(code1 == NONE)
-       break;
-      if(code1 & LEFT) 
-       {
-         tx=wx1-x1;
-         ty=y1+(tx*m);
-         x1=wx1; y1=ty;
-         code1=chGetCode(x1,y1,wx1,wy1,wx2,wy2);
-       }
-      if(code1 & RIGHT) 
-       {
-         tx=wx2-x1;
-         ty=y1+(tx*m);
-         x1=wx2; y1=ty;
-         code1=chGetCode(x1,y1,wx1,wy1,wx2,wy2);
-       }
-      if(code1 & TOP) 
-       {
-         ty=wy1-y1;
-         tx=x1+(ty/m);
-         x1=tx; y1=wy1;
-         code1=chGetCode(x1,y1,wx1,wy1,wx2,wy2);
-       }
-      if(code1 & BOTTOM)
-       {
-         ty=wy2-y1;
-         tx=x1+(ty/m);
-         x1=tx; y1=wy2;
-         code1=chGetCode(x1,y1,wx1,wy1,wx2,wy2);
-       }
-      if((code2 & code1) != 0)
-       return false;
-    }
-  if(code1 != NONE)
-    {
-      fprintf(stderr,"Bad clip: %g,%g %g,%g [%g,%g]-[%g,%g]\n",x1,y1,x2,y2,wx1,wy1,wx2,wy2);
-      return false;
-    }
-  return true;
-}
-
-static bool Clip(double &x1,double &y1,double &x2,double &y2, double wx1, double wy1, double wx2, double wy2)
-{
-  int code1=chGetCode(x1,y1,wx1,wy1,wx2,wy2);
-  int code2=chGetCode(x2,y2,wx1,wy1,wx2,wy2);
-  if((code1 & code2) != 0)
-    return false;
-  if((code1 == 0) && (code2 == 0))
-    return true;
-  //  printf("Clipping %g,%g - %g,%g to %g,%g - %g,%g\n",x1,y1,x2,y2,wx1,wy1,wx2,wy2);
-  bool res = SubClip(x1,y1,x2,y2,wx1,wy1,wx2,wy2);
-  //  printf("    Clip %g,%g - %g,%g to %g,%g - %g,%g %s\n",x1,y1,x2,y2,wx1,wy1,wx2,wy2, res ? "true" : "false");       
-  return res && SubClip(x2,y2,x1,y1,wx1,wy1,wx2,wy2);
-
-
-}
-
-void setColor(FILE *out, Fl_Color_Chooser *c)
-{
-  fprintf(out,"%g %g %g setrgbcolor %% Color: %s\n",c->r(),c->g(),c->b(),c->label());
-}
-
-void Image_Printer::write_watermark()
-{
-  // The "Watermark" prints a text copy of many of the settings into a small
-  // Rectangle clipped to the image area.  You can use illustrator to delete
-  // the image and see it if you need to duplicate an image.
-  static const double ls=5.0/INCH;
-  fprintf(out,"%% The following puts a watermark with some info on how the file was made below the image\n");
-  setColor(out,ipc->text_color);
-  pushClip(out,xoff,yoff,width,height);
-  fprintf(out,"/Courier findfont 4 scalefont setfont\n");
-  double y = yoff+height-ls;
-  char buf[4096];
-
-  snprintf(buf,sizeof(buf),"filename %s colormap %s",
-          iw->filename.c_str(), iw->colormap_window->label());
-  fprintf(out," newpath %g inch %g inch moveto (%s) show\n",
-         xoff, y, buf);
-  y -= ls;
-
-  snprintf(buf,sizeof(buf),"hmin %d %e %s hmax %d %e",
-          iw->hmin, iw->id.quant_to_raw(iw->hmin), iw->id.zname.c_str(),
-          iw->hmax, iw->id.quant_to_raw(iw->hmax));
-  fprintf(out," newpath %g inch %g inch moveto (%s) show\n",
-         xoff, y, buf);
-  y -= ls;
-
-  snprintf(buf,sizeof(buf),"plane_a %g plane_b %g gamma %g gammacenter %g", iw->plane_a, iw->plane_b, iw->gam, iw->gcenter);
-  fprintf(out," newpath %g inch %g inch moveto (%s) show\n",
-         xoff, y, buf);
-  y -= ls;
-
-  snprintf(buf,sizeof(buf),"imop \"%s\"", iw->operations_string.c_str());
-  fprintf(out," newpath %g inch %g inch moveto (%s) show\n",
-         xoff, y, buf);
-  y -= ls;
-
-  snprintf(buf,sizeof(buf),"box_int (%d,%d)-(%d,%d)", img_x1, img_y1, img_x2, img_y2);
-  fprintf(out," newpath %g inch %g inch moveto (%s) show\n",
-         xoff, y, buf);
-  y -= ls;
-
-  snprintf(buf,sizeof(buf),"box (%g,%g)-(%g,%g)", iw->xunit(img_x1)*xscale, iw->yunit(img_y1)*yscale, iw->xunit(img_x2)*xscale, iw->yunit(img_y2)*yscale);
-  fprintf(out," newpath %g inch %g inch moveto (%s) show\n",
-         xoff, y, buf);
-  y -= ls;
-
-  snprintf(buf,sizeof(buf),"xscale %g yscale %g", xscale, yscale);
-  fprintf(out," newpath %g inch %g inch moveto (%s) show\n",
-         xoff, y, buf);
-  y -= ls;
-
-
-  fprintf(out," cliprestore\n");
-}
-
-void Image_Printer::calculateBoundingBox()
-{
-  // Before, we put the bounding box at the end of the file after we
-  // calculated all the label widths.
-
-  // However, there is an outstanding ghostscript bug that ignores
-  // (atend) bounding boxes gv and gsview both have hacked together
-  // work arounds however, if we use ghostscript to convert to png or
-  // pdf, the bounding box is completely ignored!
-  
-  // So, now, we have to hack it in here.
-  
-  // The y values are easy, since the height of the labels is fixed
-  bb_ur_y = (int) ((yoff+height)*INCH + (ipc->do_title->value() ? 2 : 1) * fontsize);
-  bb_ll_y = (int) (yoff*INCH - (ipc->xaxis_label->value() ? 3 : 2) * fontsize);
-
-  // The x values are much harder, since we need to estimate the maximum width of
-  // the y axis labels and the colorbar labels. 
-  //
-  // Let's try estimating it from the min an max values of the labels
-  
-//   double tmp;
-//   char buf[128];
-//   tmp = iw->yunit((img_y2+img_y1)*0.667)*yscale; // a random uneven number?
-//   max_ytic_width = snprintf(buf,sizeof(buf),ipc->yticfmt->value(),tmp); 
-//   info("%s\n", buf);
-
-//   // Same for the colorbar
-
-//   tmp = iw->getz((iw->hmin+iw->hmax)*0.667)*zscale;
-//   max_ctic_width = snprintf(buf,sizeof(buf),ipc->yticfmt->value(),tmp);
-//   info("%s\n", buf);
-
-  // the above doesn't work so well either...
-  // let's just overestimate the bounding box a bit...
-  // it would be better to calculate the tics ahead of time...
-
-  max_ytic_width = 10;
-  max_ctic_width = 10;
-
-  int label_x = static_cast<int>(- (max_ytic_width+2.5)*fontsize/2.0);
-  bb_ll_x = (int) (xoff*INCH - (ipc->yaxis_label->value() ? 1 : -1) * fontsize + label_x); 
-
-  int label_c = static_cast<int>((max_ctic_width+2.5)*fontsize/2.0);
-  cbar_width = ipc->cbar_width->value();
-  cbar_xoff = xoff + width + 0.3;
-
-  if(ipc->colorbar->value())
-    bb_ur_x = (int) ((cbar_xoff+cbar_width)*INCH + label_c + (ipc->caxis_label->value() ? fontsize : 0));
-  else
-    bb_ur_x = (int) ((xoff+width)*INCH + fontsize);
-
-  info("Label width estimates:\n");
-  info("ytic %d ctic %d\n", max_ytic_width, max_ctic_width);
-  info("%%%%BoundingBox: %d %d %d %d\n", bb_ll_x, bb_ll_y, bb_ur_x, bb_ur_y); 
-
-  max_ytic_width = 0;
-  max_ctic_width = 0;
-}
-  
-void Image_Printer::write_header()
-{
-  
-  // First, reset the bouding box
-  bb_ll_x = bb_ll_y = 0;
-
-  // Now that we to include support for printing the area selected
-  // using the zoom window (or a manually set area), we will create
-  // some variables here that store the area of the image
-
-  if (ipc->paper_eps->value() && (!preview))
-    fprintf(out,"%%!PS-Adobe-3.0 EPSF-3.0\n");
-  else 
-    fprintf(out,"%%!PS-Adobe-3.0\n");
-
-  // Add a paper description and orientation for nice cooperation with
-  // gs: however, for some reason, ps2pdf seems to ignore the paper
-  // settings we put in the postscript file and just uses Letter...
-  if (ipc->paper_letter->value())
-    {
-      bb_ur_x = 612;
-      bb_ur_y = 792;
-    }
-  else if (ipc->paper_a4->value())
-    {
-      bb_ur_x = 595;
-      bb_ur_y = 842;
-    }
-  
-  if (ipc->paper_eps->value())
-    {
-      calculateBoundingBox();
-      fprintf(out, "%%%%BoundingBox: %d %d %d %d\n", bb_ll_x, bb_ll_y, bb_ur_x, bb_ur_y); 
-      if(preview)
-       fprintf(out, "%%%%Pages: 1\n");
-      else
-       fprintf(out, "%%%%Pages: 0\n");
-      fprintf(out,"%%%%Orientation: Portrait\n");
-    }
-  else
-    {
-      // The PNG and PDF files will be displayed with rotated pages if we do this.
-      //if (ipc->landscape->value()) 
-      //{
-      //         int tmp = bb_ur_x;
-      //         bb_ur_x = bb_ur_y;
-      //  bb_ur_y = tmp;
-      //}
-      // the above doesn't really work...
-      if (ipc->paper_letter->value())
-       fprintf(out, "%%%%DocumentMedia: Letter %d %d 0 () ()\n", bb_ur_x,bb_ur_y);
-      else if (ipc->paper_a4->value())
-       fprintf(out, "%%%%DocumentMedia: A4 %d %d 0 () ()\n",bb_ur_x,bb_ur_y);
-
-      fprintf(out, "%%%%Orientation: %s\n", ipc->landscape->value() ? "Landscape" : "Portrait");
-      fprintf(out, "%%%%Pages: 1\n");
-    }
-
-  // DSC comments that don't change with ps/eps...
-  fprintf(out,"%%%%DocumentData: Clean7Bit\n");
-  fprintf(out,"%%%%Creator: Spyview PS Output\n");
-  fprintf(out,
-         "%%%% Spyview parameters:\n"
-         "%%%% colorplotmin = %e ; colorplotmax = %e\n"
-         "%%%% gamma = %e\n"
-         "%%%% rawdata_min = %e, rawdata_max = %e\n",
-         iw->getz(iw->hmin)*zscale, iw->getz(iw->hmax)*zscale, 
-         iw->gam, iw->id.rawmin, iw->id.rawmax);
-  fprintf(out,"%%%%EndComments\n\n");
-
-
-  // Distiller magic
-  fprintf(out,
-         "%%%%BeginSetup\n"
-         "%% The following makes distiller not jpeg compress the spyview image.\n"
-         "systemdict /setdistillerparams known {\n"
-         "<< /AutoFilterColorImages false /ColorImageFilter /FlateEncode >>\n"
-         "setdistillerparams\n"
-         "} if\n"
-         "/inch {72 mul} bind def\n"
-         "/rightshow %% stk: string; show a string right aligned at the current location\n"
-         "{ dup stringwidth pop 0 exch sub 0 rmoveto show } def\n"
-         "/centershow %% stk: string show a string centered horizontally at the current location\n"
-         "{ dup stringwidth pop 0 exch sub 0.5 mul 0 rmoveto show } def\n"
-         "%%%%EndSetup\n");
-
-  if(ipc->paper_eps->value())
-    {
-      // Tricky part: estimate a nice bounding box for an EPS file; the pagesize will crop the output pdf nicely if we get it close.
-      int label_c = static_cast<int>((6)*fontsize/2.0);
-      if(ipc->colorbar->value())
-       bb_ur_x = (int) ((cbar_xoff+cbar_width)*INCH + label_c + (ipc->caxis_label->value() ? fontsize : 0));
-      else
-       bb_ur_x = (int) ((xoff+width)*INCH + fontsize);
-      bb_ur_y = (int) ((yoff+height)*INCH + (ipc->do_title->value() ? 2 : 1) * fontsize);
-
-      // This is causing problems with ghostscript 8.54: strictly
-      // speaking, EPS files should not have a page size. In newer
-      // versions of ghostscript, if a page size is found, it
-      // overrides the bounding box for conversion to, for example,
-      // PDF and PNG files.
-      //fprintf(out,"<< /PageSize [%d %d] >> setpagedevice\n",bb_ur_x,bb_ur_y);
-    }
-
-  if (!ipc->paper_eps->value() || preview)
-    fprintf(out, "%%%%Page: 1 1\n");
-  fprintf(out,"gsave\n");
-}
-
-void Image_Printer::draw_image()
-{
-
-  // Draw the image
-  fprintf(out,"%% Draw the image\n");
-  //fprintf(out,"/imgstr %d string def\n\n", iw->w);
-  fprintf(out,"/imgstr %d string def\n\n", img_xsize);
-  fprintf(out,"gsave\n  %g inch %g inch translate\n", xoff,yoff);
-  fprintf(out,"  %g inch %g inch scale\n",width,height);
-  //fprintf(out,"  %d %d %% Columns and Rows\n", iw->w, iw->h);
-  fprintf(out,"  %d %d %% Columns and Rows\n", img_xsize, img_ysize);
-  fprintf(out,"  8 %% bits per color channel\n");
-  //fprintf(out,"  [%d 0 0 %d 0 0]\n",iw->w, iw->h); // Map the unit square to our image
-  fprintf(out,"  [%d 0 0 %d 0 0]\n",img_xsize, img_ysize); // Map the unit square to our image
-  fprintf(out,"    { currentfile imgstr readhexstring pop } false 3 colorimage\n");
-  fprintf(out,"      ");
-
-  // number of columns before a newline in the postscript image
-  static const int maxcol=72;
-
-  for(int i = img_y2; i >= img_y1; i--)
-    {
-      int c = 0;
-      for(int j = img_x1; j <= img_x2; j++)
-       {
-         c += 6;
-         if(c > maxcol)
-           {
-             fprintf(out,"\n      ");
-             c = 6;
-           }
-         unsigned char r,g,b;
-         if(i >= 0 && i < iw->h &&  j >= 0 && j < iw->w) // This is a horrible hack, but I'm too lazy to work out the right bounds.
-           iw->getrgb(i,j,r,g,b);
-         else
-           {
-             r = g = b = 255;
-           }
-         fprintf(out,"%02x%02x%02x",r,g,b);
-       
-       }
-      fprintf(out,"\n      ");
-    }
-  fprintf(out,"  grestore\n\n");
-}
-
-void Image_Printer::draw_lines()
-{
-  // We want to draw the linecut before the bounding box and the tic
-  // marks, so it comes out beneath them.
-  bool clipped=false;
-
-  if(ipc->plotLineCut->value() && (iw->line_cut_type != NOLINE)) // Plot the line for the linecut.  We use the ticmark settings at the moment, which is stupid but easy.
-    {
-      pushClip(out,xoff,yoff,width,height);
-      clipped=true;      
-      fprintf(out,"%% Plot the linecut location\n");
-      setColor(out, ipc->linecut_color);      
-      fprintf(out," %g setlinewidth newpath\n",tickwidth);
-      double x1,y1,x2,y2,t;
-      switch(iw->line_cut_type)
-       {
-       case HORZLINE:
-         x1 = xoff; x2 = xoff + width;
-         y1=iw->line_cut_yp;
-         pixelToDevice(t,y1);
-         y2=y1;
-         break;
-       case VERTLINE:
-         x1=iw->line_cut_xp;
-         pixelToDevice(x1,t);
-         x2=x1;
-         y1 = yoff; y2 = yoff + height;
-         break;
-       case OTHERLINE:
-         x1=iw->lcx1;
-         x2=iw->lcx2;
-         y1=iw->lcy1;
-         y2=iw->lcy2;
-         pixelToDevice(x1,y1);
-         pixelToDevice(x2,y2);
-         break;
-       default:
-         warn("Unknown line cut type!\n");
-         exit(1);
-       }
-      fprintf(out,"     %g inch %g inch moveto\n",x1,y1);
-      fprintf(out,"     %g inch %g inch lineto\n",x2,y2);
-      fprintf(out,"stroke\n");
-    }
-
-  if(ipc->plotZoomBox->value() && iw->zoom_window && iw->zoom_window->visible())
-    {
-      int x1,y1,x2,y2;
-      iw->zoom_window->getSourceArea(x1,y1,x2,y2);
-      double x1d, y1d, x2d, y2d;
-      x1d = x1; y1d = y1; x2d = x2; y2d = y2;
-      pixelToDevice(x1d,y1d);
-      pixelToDevice(x2d,y2d);
-      setColor(out,ipc->zoombox_color);
-      fprintf(out," %g setlinewidth newpath\n",tickwidth);
-      fprintf(out," %g inch %g inch moveto\n",x1d,y1d);
-      fprintf(out," %g inch %g inch lineto\n",x1d,y2d);
-      fprintf(out," %g inch %g inch lineto\n",x2d,y2d);
-      fprintf(out," %g inch %g inch lineto\n",x2d,y1d);
-      fprintf(out," %g inch %g inch lineto\n",x1d,y1d);
-      fprintf(out," stroke\n");
-    }
-  if (ipc->plotLines->value() && !LineDrawer->lines.empty())
-    {
-      if(!clipped)
-       pushClip(out,xoff,yoff,width,height);
-      clipped=true;
-      fprintf(out,"%% Plot the lines\n");
-      setColor(out,ipc->overlay_color);
-      fprintf(out,"%g setlinewidth newpath\n",tickwidth);
-      double lx = NAN;
-      double ly = NAN;
-
-      for(LineDraw::lines_t::iterator i = LineDrawer->lines.begin(); i != LineDrawer->lines.end(); i++)
-       {
-         double x1,y1,x2,y2;
-         x1=i->x1*xscale;
-         x2=i->x2*xscale;
-         y1=i->y1*yscale;
-         y2=i->y2*yscale;
-         unitToDevice(x1,y1);
-         unitToDevice(x2,y2);
-         if(Clip(x1,y1,x2,y2,xoff,yoff,xoff+width,yoff+height))
-           {
-             if(!(isnan(x1) || isnan(y1) || isnan(x2) || isnan(y2)))
-               {
-                 if((x1 != lx) || (y1 != ly)) // Skip unnecessary moves.
-                   fprintf(out,"     %g inch %g inch moveto\n",x1,y1);
-                 fprintf(out,"     %g inch %g inch lineto\n",x2,y2);
-               }
-             lx = x2;
-             ly = y2;
-           }
-         else
-           {
-             lx = NAN;
-             ly = NAN;
-           }
-       }
-      fprintf(out,"stroke\n");
-    }
-  if(clipped)
-    {
-      fprintf(out," cliprestore\n");
-      clipped=false;
-    }
-}
-
-void Image_Printer::draw_colorbar()
-{
-  int cbimgx, cbimgy;
-  if (ipc->rotate_cbar->value())
-    {
-      cbar_height = ipc->cbar_width->value();
-      cbar_width = height*ipc->cbar_height_per->value()/100.0;
-      cbar_xoff = xoff + (width-cbar_width)/2;
-      cbar_yoff = yoff + height+0.3;
-      cbimgx = iw->colormap_length;
-      cbimgy = 1;
-    }
-  else
-    {
-      cbar_width = ipc->cbar_width->value();
-      cbar_height = height*ipc->cbar_height_per->value()/100.0;
-      cbar_xoff = xoff + width + 0.3;
-      cbar_yoff = yoff + (height - cbar_height)/2;
-      cbimgx = 1;
-      cbimgy = iw->colormap_length;
-    }
-
-
-
-  if (!ipc->linear_cmap->value())
-    {
-      // Draw a colorbar with a non-linear color mapping but a linear tic spacing
-  
-      fprintf(out,"%% Draw the colorbar\n");
-      fprintf(out,"/imgstr %d string def\n\n", 1);
-      fprintf(out,"gsave\n  %g inch %g inch translate\n", cbar_xoff, cbar_yoff);
-      fprintf(out,"  %g inch %g inch scale\n",cbar_width, cbar_height);
-      fprintf(out,"  %d %d %% Columns and Rows\n", cbimgx, cbimgy);
-      fprintf(out,"  8 %% bits per color channel\n");
-      fprintf(out,"  [%d 0 0 %d 0 0]\n", cbimgx, cbimgy); // Map the unit square to our image
-      fprintf(out,"    { currentfile imgstr readhexstring pop } false 3 colorimage\n");
-
-      int tmp;
-      for(int i = 0; i < iw->colormap_length; i++)
-       {
-         unsigned char r,g,b;
-         tmp = iw->gammatable[i];
-         r = iw->colormap[3*tmp];
-         g = iw->colormap[3*tmp+1];
-         b = iw->colormap[3*tmp+2];
-         fprintf(out,"%02x%02x%02x",r,g,b);
-         fprintf(out,"\n      ");
-       }
-      fprintf(out,"  grestore\n\n");
-
-      // Draw the colorbar box
-  
-      if (boxwidth > 0)
-       {
-         fprintf(out, "%% Draw the box around the colorbar\n");
-         setColor(out,ipc->border_color);
-         fprintf(out,"  %g setlinewidth newpath\n",boxwidth);
-         box(out,cbar_xoff,cbar_yoff,cbar_width,cbar_height);
-         fprintf(out,"  stroke\n");
-       }
-
-      // Draw the tic marks on the colorbox
-      fprintf(out,"/%s findfont %g scalefont setfont\n",ipc->face->value(),fontsize);
-      fprintf(out,"  %g setlinewidth\n", tickwidth);
-      if(ipc->cticfmt->size() != 0)
-       {
-         double cs;
-         double cmin = iw->getz(iw->hmin)*zscale;
-         double cmax = iw->getz(iw->hmax)*zscale;
-         int tic_width;
-      
-         if(ipc->cspacing->value() != 0)
-           cs = fabs(ipc->cspacing->value());
-         else
-           cs=autospace(cmin,cmax);
-
-         if(cmin > cmax)
-           cs=-cs;
-      
-         // Tic marks should be on integers (1.0, 1.5,... not 1.37,1.87,...) and should not be outside the frame
-         double min = cs*ceil(cmin/cs);
-         double tic_offset, wrange;
-         if (ipc->precise_ticks->value())
-           {
-             wrange=cbar_height*(iw->colormap_length-1)/(iw->colormap_length);  // cmin is actually 1/2 picel from the left edge, xmax is 1/2 pixel from the right.
-             tic_offset = cbar_height*(0.5/(iw->colormap_length));
-           }
-         else 
-           {
-             wrange=cbar_height;
-             tic_offset=0;
-           }
-         //      warn("min %g cmin %g cmax %g cs %g zero %g\n",min,cmin,cmax,cs,zero);
-         for(double c = min; c*cs <= cmax*cs + zero*cs*fabs(cs); c += cs)
-           {
-             //              warn("%g %g %g %g\n",c,c*cs,cmax*cs,zero*cs*abs(cs));
-             //if(x < xmin)
-             //continue;
-             char buf[128];
-             buf[0] = 0; // a good default
-             if (ipc->cticfmt->value()[0] == 'e')
-               {
-                 char *p = ipc->cticfmt->value()+1;
-                 long int dig = strtol(p, (char **)NULL, 10); // strtol returns zero if no digits are found
-                 if (dig == 0) dig = 2; // a reasonable default?
-                 strncpy(buf, eng(c, dig, 1), 128);
-               }
-             else if (ipc->cticfmt->value()[0] == 's')
-               {
-                 char *p = ipc->cticfmt->value()+1;
-                 long int dig = strtol(p, (char **)NULL, 10); // strtol returns zero if no digits are found
-                 if (dig == 0) dig = 2; // a reasonable default?
-                 strncpy(buf, eng(c, dig, 0), 128);
-               }
-             else
-               {
-                 if(fabs(c/cs) < zero)
-                   snprintf(buf,sizeof(buf),ipc->cticfmt->value(),0.0);
-                 else
-                   snprintf(buf,sizeof(buf),ipc->cticfmt->value(),c);
-               }
-             info("cvalue %e label '%s'\n", c, buf);
-             tic_width = strlen(buf);
-
-             if (tic_width > max_ctic_width) max_ctic_width = tic_width;
-         
-             double psx = cbar_xoff+cbar_width+0.25*fontsize/INCH; //
-             double psy = cbar_yoff + wrange * ((c-cmin)/(cmax-cmin)) + tic_offset;
-             setColor(out,ipc->text_color);
-             fprintf(out,"  newpath %g inch %g inch moveto (%s) show\n",psx,psy-0.25*fontsize/INCH,buf);
-
-             if(ipc->fancy_ticks->value())
-               {
-                 setColor(out,ipc->large_tick_color);
-                 fprintf(out,"%g setlinewidth newpath\n",tickwidth*2);
-                 fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",cbar_xoff,psy,ticklength+tickwidth/72.0);
-                 fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",cbar_xoff+cbar_width,psy,-ticklength-tickwidth/72.0);     
-                 setColor(out,ipc->small_tick_color);
-                 fprintf(out,"%g setlinewidth newpath\n",tickwidth);
-                 fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",cbar_xoff,psy,ticklength);
-                 fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",cbar_xoff+cbar_width,psy,-ticklength);     
-               }
-             else
-               {
-                 setColor(out,ipc->small_tick_color);
-                 fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",cbar_xoff,psy,ticklength);
-                 fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",cbar_xoff+cbar_width,psy,-ticklength);     
-               }
-           }
-       }
-    }
-  else // Draw a colorbar with a linear color scale but with a non-linear tic mark scale
-    {
-
-      // First draw the image for inside the colorbar
-
-      int length = iw->colormap_length;
-      int start = ipc->cmin->value()*length;
-      int end = ipc->cmax->value()*length;
-
-      fprintf(out,"%% Draw the colorbar\n");
-      fprintf(out,"/imgstr %d string def\n\n", 1);
-      fprintf(out,"gsave\n  %g inch %g inch translate\n", cbar_xoff, cbar_yoff);
-      fprintf(out,"  %g inch %g inch scale\n",cbar_width, cbar_height);
-      fprintf(out,"  %d %d %% Columns and Rows\n", 1, end-start);
-      fprintf(out,"  8 %% bits per color channel\n");
-      fprintf(out,"  [%d 0 0 %d 0 0]\n", 1, end-start); // Map the unit square to our image
-      fprintf(out,"    { currentfile imgstr readhexstring pop } false 3 colorimage\n");
-
-      for(int i = start; i < end; i++)
-       {
-         unsigned char r,g,b;
-         r = iw->colormap[3*i];
-         g = iw->colormap[3*i+1];
-         b = iw->colormap[3*i+2];
-         fprintf(out,"%02x%02x%02x",r,g,b);
-         fprintf(out,"\n      ");
-       }
-      fprintf(out,"  grestore\n\n");
-
-      // Draw the colorbar box
-  
-      if (boxwidth > 0)
-       {
-         setColor(out,ipc->border_color);
-         fprintf(out, "%% Draw the box around the colorbar\n");
-         fprintf(out,"  %g setlinewidth newpath\n",boxwidth);
-         box(out,cbar_xoff,cbar_yoff,cbar_width,cbar_height);
-         fprintf(out,"  stroke\n");
-       }
-
-      // Now, we want to do something a bit tricky: map the colors on
-      // the "linear" color scale onto actual data values for tick
-      // marks. The first thing we need to do is make what I will call
-      // a "reverse map". Using this table, we can get a datapoint
-      // value based on it's color value
-
-      // We have to be a bit careful with rounding, particularly for
-      // small gammas
-      int l = iw->colormap_length;
-      int reverse_map[l];
-      for (int i=0; i<l; i++)
-       reverse_map[i] = -1;
-      for (int i=iw->hmin; i<iw->hmax; i++)
-       {
-         int index = 1.0*iw->imagehist[i]*(l-1)/LMAX;
-         if (reverse_map[index] == -1) reverse_map[index] = i;
-       }
-      reverse_map[0] = iw->hmin;
-      for (int i=0; i<l; i++)
-       if (reverse_map[i] == -1) reverse_map[i] = reverse_map[i-1];
-       
-      // Now try to work out what the beginning color should be such
-      // that we try to end up with a label at the value that the user
-      // has asked for
-
-      // TODO: FIX this at some point...
-      
-      double definitive_label = ipc->cbegin->value(); // will leave this name unchanged to avoid having to rewrite settings code...
-      double c1=-1;
-      // Get the quantized value from the raw value
-      int val_quant = iw->id.raw_to_quant(definitive_label);
-      // Get the position in the un-gammed colormap (float between 0 and 1)
-      double cmap_position = iw->imagehist[val_quant]/LMAX; 
-      info("estimated cmap position is %f\n", cmap_position);
-      if (c1 < ipc->cmin->value()) c1 = ipc->cmin->value();
-
-      // Draw the tic marks on the colorbox
-      fprintf(out,"/%s findfont %g scalefont setfont\n",ipc->face->value(),fontsize);
-      fprintf(out,"  %g setlinewidth\n", tickwidth);
-      char buf[256];
-      if(ipc->cticfmt->size() != 0)
-       {
-         for (double c=c1; c < ipc->cmax->value(); c += ipc->clabelspacing->value())
-           {
-             int i = (int) (c*(l-1));
-             double val = iw->id.quant_to_raw(reverse_map[i]);
-
-             buf[0] = 0; // a good default
-             if (ipc->cticfmt->value()[0] == 'e')
-               {
-                 char *p = ipc->cticfmt->value()+1;
-                 long int dig = strtol(p, (char **)NULL, 10); // strtol returns zero if no digits are found
-                 if (dig == 0) dig = 2; // a reasonable default?
-                 strncpy(buf, eng(c, dig, 1), 128);
-               }
-             else if (ipc->cticfmt->value()[0] == 's')
-               {
-                 char *p = ipc->cticfmt->value()+1;
-                 long int dig = strtol(p, (char **)NULL, 10); // strtol returns zero if no digits are found
-                 if (dig == 0) dig = 2; // a reasonable default?
-                 strncpy(buf, eng(c, dig, 0), 128);
-               }
-             else
-               snprintf(buf,sizeof(buf),ipc->cticfmt->value(),c);
-             info("cvalue %e label '%s'\n", c, buf);
-             int tic_width = strlen(buf);
-
-             if (tic_width > max_ctic_width) max_ctic_width = tic_width;
-
-             double psx = cbar_xoff + cbar_width + 0.25*fontsize/INCH; 
-             double psy = cbar_yoff + cbar_height * ((c-ipc->cmin->value())/(ipc->cmax->value()-ipc->cmin->value()));
-                 
-             // Draw the label
-             setColor(out,ipc->text_color);
-             fprintf(out,"  newpath %g inch %g inch moveto (%s) show\n",psx,psy-0.25*fontsize/INCH,buf);
-
-             // Draw the tic lines
-             if(ipc->fancy_ticks->value())
-               {
-                 setColor(out,ipc->large_tick_color);
-                 fprintf(out,"%g setlinewidth newpath\n",tickwidth*2);
-                 fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",cbar_xoff,psy,ticklength+tickwidth/72.0);
-                 fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",cbar_xoff+cbar_width,psy,-ticklength-tickwidth/72.0);     
-                 setColor(out,ipc->small_tick_color);
-                 fprintf(out,"%g setlinewidth newpath\n",tickwidth);
-                 fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",cbar_xoff,psy,ticklength);
-                 fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",cbar_xoff+cbar_width,psy,-ticklength);     
-               }
-             else
-               {
-                 setColor(out,ipc->small_tick_color);
-                 fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",cbar_xoff,psy,ticklength);
-                 fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",cbar_xoff+cbar_width,psy,-ticklength);     
-               }
-           }
-       }
-    }
-}
-
-void Image_Printer::draw_axis_tics()
-{
-
-  // *****************
-  // Draw the xtics
-  // *****************
-
-  // Draw the tick marks  
-  fprintf(out,"/%s findfont %g scalefont setfont\n",ipc->face->value(),fontsize);
-  fprintf(out,"  %g setlinewidth\n", tickwidth);
-  if(ipc->xticfmt->value()[0] != '\0')
-    {
-      double xs;
-      double xmin = iw->xunit(img_x1)*xscale;
-      double xmax = iw->xunit(img_x2)*xscale;
-      
-      if(xspacing != 0)
-       xs = fabs(xspacing);
-      else
-       xs=autospace(xmin,xmax);
-
-      if(xmin > xmax)
-       xs=-xs;
-      
-      // Tic marks should be on integers (1.0, 1.5,... not 1.37,1.87,...) and should not be outside the frame
-      double min = xs*ceil(xmin/xs);
-      double tic_offset, wrange;
-      if (ipc->precise_ticks->value())
-       {
-         wrange=width*(img_xsize-1)/(img_xsize);  // xmin is actually 1/2 pixel from the left edge, xmax is 1/2 pixel from the right.
-         tic_offset = width*(0.5/(img_xsize));
-       }
-      else 
-       {
-         wrange=width;
-         tic_offset=0;
-       }
-      for(double x = min; x*xs <= xmax*xs + zero*xs*fabs(xs); x += xs)
-       {
-         //if(x < xmin)
-         //continue;
-         char buf[128];
-         buf[0] = 0; // a good default
-         if (ipc->xticfmt->value()[0] == 'e')
-           {
-             char *p = ipc->xticfmt->value()+1;
-             long int dig = strtol(p, (char **)NULL, 10); // strtol returns zero if no digits are found
-             if (dig == 0) dig = 2; // a reasonable default?
-             strncpy(buf, eng(x, dig, 1), 128);
-           }
-         else if (ipc->xticfmt->value()[0] == 's')
-           {
-             char *p = ipc->xticfmt->value()+1;
-             long int dig = strtol(p, (char **)NULL, 10); // strtol returns zero if no digits are found
-             if (dig == 0) dig = 2; // a reasonable default?
-             strncpy(buf, eng(x, dig, 0), 128);
-           }
-         else
-           {
-             if(fabs(x/xs) < zero)
-               snprintf(buf,sizeof(buf),ipc->xticfmt->value(),0.0);
-             else
-               snprintf(buf,sizeof(buf),ipc->xticfmt->value(),x);
-           }
-         //info("xvalue %e label '%s'\n", x, buf);
-
-         double psy = yoff-1.0*fontsize/INCH; //
-         double psx = xoff + wrange * ((x-xmin)/(xmax-xmin)) + tic_offset;
-         setColor(out,ipc->text_color);
-         fprintf(out,"  newpath %g inch %g inch moveto (%s) centershow\n",psx,psy,buf);
-         if(ipc->fancy_ticks->value())
-           {
-             setColor(out,ipc->large_tick_color);
-             fprintf(out,"%g setlinewidth newpath\n",tickwidth*2);
-             fprintf(out,"  newpath %g inch %g inch moveto 0 %g inch rlineto stroke\n",psx,yoff,ticklength+tickwidth/72.0);
-             fprintf(out,"  newpath %g inch %g inch moveto 0 %g inch rlineto stroke\n",psx,yoff+height,-ticklength-tickwidth/72.0);
-             setColor(out,ipc->small_tick_color);
-             fprintf(out,"%g setlinewidth newpath\n",tickwidth);
-             fprintf(out,"  newpath %g inch %g inch moveto 0 %g inch rlineto stroke\n",psx,yoff,ticklength);
-             fprintf(out,"  newpath %g inch %g inch moveto 0 %g inch rlineto stroke\n",psx,yoff+height,-ticklength);
-           }
-         else
-           {
-             setColor(out,ipc->small_tick_color);
-             fprintf(out,"  newpath %g inch %g inch moveto 0 inch %g inch rlineto stroke\n",psx,yoff,ticklength);
-             fprintf(out,"  newpath %g inch %g inch moveto 0 inch %g inch rlineto stroke\n",psx,yoff+height,-ticklength);
-           }
-       }
-      
-
-    }
-
-  // *****************
-  // Draw the ytics
-  // *****************
-
-  if(ipc->yticfmt->value()[0] != '\0')
-    {
-      double ys;
-      // we have some issues due to the fact that "y=0" for the fltk
-      // drawing routines is at the top of the screen...we must
-      // remember that ymax = y1 and ymin = y2...
-      double ymin = iw->yunit(img_y2)*yscale; 
-      double ymax = iw->yunit(img_y1)*yscale;
-
-      if(yspacing != 0)
-       ys = fabs(yspacing);
-      else
-       ys=autospace(ymin,ymax);
-
-      if(ymin > ymax)
-       ys=-ys;
-
-      int tic_width;
-      
-      // This is horrible; everything changes when ys and ymin change sign.
-      double min = ys*ceil(ymin/ys);
-      double hrange, tic_offset;
-      if (ipc->precise_ticks->value())
-       {
-         hrange = height*(img_ysize-1)/(img_ysize);
-         tic_offset = height*(0.5/(img_ysize)); 
-       }
-      else
-       {
-         hrange = height;
-         tic_offset = 0;
-       }
-      for(double y = min; y*ys <= ymax*ys + zero*ys*fabs(ys); y += ys)
-       {
-         //      warn("%g\n",y);
-         char buf[128];
-         buf[0] = 0; // a good default
-         if (ipc->yticfmt->value()[0] == 'e')
-           {
-             char *p = ipc->yticfmt->value()+1;
-             long int dig = strtol(p, (char **)NULL, 10); // strtol returns zero if no digits are found
-             if (dig == 0) dig = 2; // a reasonable default?
-             strncpy(buf, eng(y, dig, 1), 128);
-           }
-         else if (ipc->yticfmt->value()[0] == 's')
-           {
-             char *p = ipc->yticfmt->value()+1;
-             long int dig = strtol(p, (char **)NULL, 10); // strtol returns zero if no digits are found
-             if (dig == 0) dig = 2; // a reasonable default?
-             strncpy(buf, eng(y, dig, 0), 128);
-           }
-         else
-           {
-             if(fabs(y/ys) < zero)
-               snprintf(buf,sizeof(buf),ipc->yticfmt->value(),0.0);
-             else
-               snprintf(buf,sizeof(buf),ipc->yticfmt->value(),y);
-           }
-         //info("yvalue %e label '%s'\n", y, buf);
-         tic_width = strlen(buf);
-
-         if (tic_width > max_ytic_width) max_ytic_width = tic_width;
-         double psx = xoff-0.25*fontsize/INCH; //
-         double psy = yoff + hrange * ((y-ymin)/(ymax-ymin)) + tic_offset;
-         setColor(out,ipc->text_color);
-         fprintf(out,"  newpath %g inch %g inch moveto (%s) rightshow\n",psx,psy-0.25*fontsize/INCH,buf);
-
-         if(ipc->fancy_ticks->value())
-           {
-             setColor(out,ipc->large_tick_color);
-             fprintf(out,"%g setlinewidth newpath\n",tickwidth*2);
-             fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",xoff,psy,ticklength+tickwidth/72.0);
-             fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",xoff+width,psy,-ticklength-tickwidth/72.0);
-             setColor(out,ipc->small_tick_color);
-             fprintf(out,"%g setlinewidth newpath\n",tickwidth);
-             fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",xoff,psy,ticklength);
-             fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",xoff+width,psy,-ticklength);
-           }
-         else
-           {
-             setColor(out,ipc->small_tick_color);
-             fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",xoff,psy,ticklength);
-             fprintf(out,"  newpath %g inch %g inch moveto %g inch 0 rlineto stroke\n",xoff+width,psy,-ticklength);
-           }
-       }
-    }
-}
-
-void Image_Printer::draw_axis_labels()
-{
-
-  // Draw the labels
-  
-  double label_x, label_y;
-  
-  setColor(out,ipc->text_color);
-  if (ipc->yaxis_label->value())
-    {
-      // Notes: as a nasty hack, assume an average font aspect ration
-      // of 2:1. Also, offset us by an extra 3.5 font widths (note
-      // max_ytic_width includes terminating null)
-
-      // Would probably be better to keep a copy of the longest ytic
-      // string and then have the postscript interpret the
-      // width for us...but this seems to work reasonably well.
-
-      label_x = xoff - (max_ytic_width+2.5)*fontsize/2.0/INCH;
-      label_y = yoff + height/2;
-      fprintf(out, " newpath %g inch %g inch moveto (%s) 90 rotate centershow -90 rotate\n", label_x, label_y, iw->id.yname.c_str());
-    }
-
-  if (ipc->caxis_label->value() && ipc->colorbar->value())
-    {
-      label_x = cbar_xoff + cbar_width + (max_ctic_width+3.5)*fontsize/2.0/INCH;
-      label_y = cbar_yoff + cbar_height/2;
-      fprintf(out, " newpath %g inch %g inch moveto (%s) 90 rotate centershow -90 rotate\n", label_x, label_y, iw->id.zname.c_str());
-    }
-  
-  if (ipc->xaxis_label->value())
-    {
-      label_x = xoff + width/2;
-      label_y = yoff - 2.5*fontsize/INCH;
-      fprintf(out, " newpath %g inch %g inch moveto (%s) centershow\n", label_x, label_y, iw->id.xname.c_str());
-    }
-
-  if (ipc->do_title->value())
-    {
-      label_x = xoff + width/2;
-      label_y = yoff + height + 1.0*fontsize/INCH;
-      char buf[1024]; 
-      char bn[1024];
-      strncpy(bn, iw->output_basename, sizeof(bn));
-      char *p = basename(bn);
-      info("%s -> %s\n", iw->output_basename, p);
-      snprintf(buf, 1024, ipc->title->value(), p, iw->id.zname.c_str());
-      // Postscript needs to have double \\ to display properly
-      string name = buf;
-      string::size_type pos=0;
-      while ((pos = name.find("\\", pos+2)) != string::npos)
-       name.replace(pos, 1, "\\\\");
-      fprintf(out, " newpath %g inch %g inch moveto (%s) centershow\n", label_x, label_y, name.c_str());
-    }
-}
-
-void Image_Printer::add_dirstamp()
-{
-  double label_x, label_y;
-  if  (ipc->paper_eps->value())
-    {
-      label_x = bb_ur_x/INCH - 0.25;
-      label_y = bb_ll_y/INCH - 0.25;
-      bb_ll_y -= 0.25*INCH + 5;
-    }
-  else
-    {
-      label_x = page_width - 0.25;
-      label_y = 0.25;
-    }
-  char buf[PATH_MAX];
-  getcwd(buf, PATH_MAX);
-  string name = buf;
-  string::size_type pos=0;
-  while ((pos = name.find("\\", pos+2)) != string::npos)
-    name.replace(pos, 1, "\\\\");
-  fprintf(out,"/%s findfont %g scalefont setfont\n",ipc->face->value(),10.0);
-  fprintf(out, " newpath %g inch %g inch moveto (%s) rightshow\n", label_x, label_y, name.c_str());
-}
diff --git a/spyview/ImageWindow.C.~1.295.~ b/spyview/ImageWindow.C.~1.295.~
deleted file mode 100644 (file)
index 8b9fde6..0000000
+++ /dev/null
@@ -1,2710 +0,0 @@
-#include <assert.h>
-#include <string>
-#include <FL/fl_ask.H>
-#include <sys/time.h>
-#include "ImageWindow.H"
-#include "ImagePrinter.H"
-#include "math.h"
-#include "message.h"
-#include <FL/Fl_Color_Chooser.H>
-#include <stdarg.h>
-#include "throttle.H"
-#include "ImageWindow_Module.H"
-#include <ctype.h>
-
-#ifdef WIN32
-
-#include <windows.h>
-
-// For win32 gettimeofday():
-// Copied from http://www.cpp-programming.net/c-tidbits/gettimeofday-function-for-windows/
-#include <time.h>
-#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
-#define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
-#else
-#define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
-#endif
-
-#endif
-
-// Bitwise if and only if
-//#define iff(A,B) ((A & B) && !(A & !B)) 
-// not as useful as I thought since events also include numlock...
-
-#define ctrl(state)  ( (state & FL_CTRL) && !(state & FL_SHIFT) && !(state & FL_ALT))
-#define shift(state) (!(state & FL_CTRL) &&  (state & FL_SHIFT) && !(state & FL_ALT))
-#define alt(state)   (!(state & FL_CTRL) && !(state & FL_SHIFT) &&  (state & FL_ALT))
-#define none(state)  (!(state & FL_CTRL) && !(state & FL_SHIFT) && !(state & FL_ALT))
-
-using namespace std;
-
-FILE *fopenwarn(const char *name, const char *mode)
-{
-  FILE *fp = fopen(name, mode);
-  
-  if (fp == NULL)
-    warn("Could not open file %s in mode \"%s\": %s\n", name, mode, strerror(errno));
-  return fp;
-}
-
-static void nognuplot()
-{
-  static bool warned = false;
-  if(warned)
-    return;
-#ifdef WIN32
-  warn("Gnuplot is not available.  Please install gnuplot for windows and put it on your path.\n");
-#else
-  warn("Unable to open gnuplot\n");
-#endif
-}
-
-
-void ImageWindow::make_tmpfiles()
-{
-
-  // If we can, we will use local files xsection.dat, hist.dat and
-  // cmap.dat in the current directory, as a convenient way to give
-  // the user access to this data
-  //
-  // If we can't (ie. directory is read only), we will use files in /tmp.
-
-  FILE *fp;
-  static int ntries;
-
-  snprintf(xsection_fn, sizeof(xsection_fn), "%sxsection.%d.dat.%d", Gnuplot_Interface::tmpdir(), ntries, getpid());
-  if ((fp = fopen(xsection_fn, "w")) == NULL)
-    { error("Failed to create tempfile %s: %s\n", xsection_fn, strerror(errno)); }
-  else fclose(fp);
-
-  snprintf(xsection_tmp_fn, sizeof(xsection_fn), "%sxsection.%d.dat.tmp_%d", Gnuplot_Interface::tmpdir(), ntries, getpid());
-  if ((fp = fopen(xsection_fn, "w")) == NULL)
-    { error("Failed to create tempfile %s: %s\n", xsection_tmp_fn, strerror(errno)); }
-  else fclose(fp);
-
-  snprintf(cmap_fn, sizeof(cmap_fn), "%scmap.%d.dat.%d", Gnuplot_Interface::tmpdir(), ntries, getpid());
-  if ((fp = fopen(cmap_fn, "w")) == NULL)
-    { error("Failed to create tempfile %s: %s\n", cmap_fn, strerror(errno)); }
-  else fclose(fp);
-
-  snprintf(hist_fn, sizeof(hist_fn), "%shist.%d.dat.%d", Gnuplot_Interface::tmpdir(), ntries, getpid());
-  if ((fp = fopen(hist_fn, "w")) == NULL)
-    { error("Failed to create tempfile %s: %s\n", hist_fn, strerror(errno)); }
-  else fclose(fp);
-
-  info("Locations of temporary files:\n%s\n%s\n%s\n", xsection_fn, cmap_fn, hist_fn);
-}
-
-ImageWindow::ImageWindow(int w, int h, const char *title) : 
-  Fl_Overlay_Window(w,h) , ipc(this) , pfc(this) 
-{
-  stupid_windows_focus = getenv("SPYVIEW_CLICKY") == NULL;
-    
-  gplinecut.bidirectional=true;
-  line_cut_limit = HORZLINE | VERTLINE | OTHERLINE | NOLINE;
-  //size_range(1,1);
-  zoomWindowDragging = ZOOM_NO;
-  statusCallback = NULL;
-  datamin = 0; datamax = LMAX;
-  hmin = 0; hmax = LMAX;
-
-  xzoom = yzoom = 1;
-  swap_zoom_state=false;
-  square = 0;
-  line_cut_type = NOLINE;
-  line_cut_xauto = 1;
-  plot_hist = false;
-  plot_cmap = false;
-  bpercent = 0.1; wpercent = 0.1;
-  //  plane_a = plane_b = plane_c = 0;
-  process_queue = NULL;
-  controls_window = NULL;
-  external_update = NULL;
-  drag_n_drop = NULL;
-  window_size_action = KEEPZOOM;
-  cmap_min = 0.0;
-  cmap_max = 1.0;
-
-  sprintf(gp_using_string, "1:2");
-  gp_with_string = "lp";
-
-  lc_axis = DISTANCE;
-
-  make_tmpfiles();
-  
-  // By default, install an 8 bit greyscale colormap.
-  colormap_length = 256;
-  colormap = new uchar[colormap_length*3];
-  gammatable = new int[colormap_length];
-
-  for (int i=0; i<256; i++)
-    colormap[3*i] = colormap[3*i+1] = colormap[3*i+2] = i;
-  
-  gam = 1;
-  gcenter = 0.0;
-  for (int i=0; i<256; i++)
-    gammatable[i] = i;
-
-  // Create the colormap window
-  colormap_window = new ColormapWindow(256,25);
-  colormap_window->img = this;
-  colormap_window->label("Colormap");
-  //  Colormap window is now controlled from UI.  Don't show by default.
-  //  colormap_window->show();
-
-  imageprinter = new Image_Printer(this, &ipc);
-
-  // Note: pfc is initialized with the constructor of ImageWindow 
-  pf = new PeakFinder(this, &pfc);
-}
-
-void ImageWindow::resize(int x, int y, int wp, int hp)
-{
-  int target_xzoom, target_yzoom;
-
-  // This is tricky...
-
-  if (wp == w) target_xzoom = 1; // Zoom should be 1
-  else if (wp*(-xzoom) == w) target_xzoom = -w/wp; // Requested size corresponds exactly to a negative zoom
-  else if (wp < w && wp*(-xzoom) != w) target_xzoom = -w/(wp+1)-1;  //Negative zoom, need to trucate downwards (-1) and be careful of images with odd number of points (wp+1)
-  else target_xzoom = wp/w; // Positive zoom: truncation has desired effect, odd number of points not a problem.
-
-  if (hp == h) target_yzoom = 1;
-  else if (hp < h && hp*(-yzoom) != h) target_yzoom = -h/(hp+1)-1;
-  else if (hp*(-yzoom) == h) target_yzoom = -h/hp; 
-  else target_yzoom = hp/h;
-
-  if (xzoom != target_xzoom || yzoom != target_yzoom)
-    {
-      xzoom = target_xzoom;
-      yzoom = target_yzoom;
-      allocateImage();
-    }
-
-  external_update();
-  size_range(1,1);
-  Fl_Overlay_Window::resize(x,y,wp,hp);
-}
-
-ImageWindow::~ImageWindow()
-{
-  if(imageprinter)
-    delete imageprinter;
-  unlink(xsection_fn);
-  unlink(cmap_fn);
-  unlink(hist_fn);
-  unlink(xsection_tmp_fn);
-  unlink("xsection.dat");
-  unlink("cmap.dat");
-  unlink("hist.dat");
-}
-
-void ImageWindow::draw() 
-{
-  if (!id.data_loaded) return;
-  imageprinter->updatePreview();
-  
-  // data = original data read from file
-  //
-  // databuf = copy of data[] to store grey data in after we've performed integer
-  //           operations, like rescaling the contrast using the imagehist lookup
-  //           table, appling the gamma scaling using the gammatable lookup
-  //           table, and performing the plane subtraction.
-  //
-  // Data starts off in data[] in whatever range of values that is
-  // occupied in the input image.
-  //
-  // After plane subtraction, data may exceed LMAX or be less than 0,
-  // so we need to trucate these values.
-  //
-  // The data between hmin and hmax then gets mapped to 0 to LMAX by
-  // the imagehist lookup table.
-  //
-  // The gammatable lookup is then applied, and each pixel in the
-  // databuf array will then have a value that ranges from 0 to
-  // colormap_length-1.
-  //
-  // In the final step, the colormap lookup table is applied, which is
-  // used to map the data onto a 8x8x8 bit RGB image.
-  
-  //  warn("Drawing %dx%d image, xzoom=%d, yzoom=%d, total=%dx%d (%d bytes)\n",
-  //     w,h,xzoom,yzoom,w*xzoom,h*yzoom,3*(w*xzoom+h*yzoom));
-
-  // This next chunk of code centers the image.  It should only matter if we're displaying an image bigger than
-  // 255x255, in which case by resizing the window manually, the user can make the window not be an intereger
-  // zoom of the original image.
-  // Zooming by using < and > will still always give an integer zoom.
-  int ox, oy; // X and Y offsets.
-  ox = Fl_Overlay_Window::w() - w*xzoom;
-  oy = Fl_Overlay_Window::h() - h*yzoom;
-  if(ox != 0 || oy != 0)
-    {
-      ox /= 2; // Center the image.  We don't do this outside the if so if the image is only 1 pixel too small,
-      oy /= 2; // we still fill in the border in black.
-      fl_color(FL_BLACK);
-      fl_rectf(0,0,Fl_Overlay_Window::w(), Fl_Overlay_Window::h());
-    }
-  ox=0; // Argh!  Centering the image kills the line cuts!  Too lazy to fix this right.
-  oy=0;
-
-  // Ok, let's finally clean this up a bit. I will now make this
-  // compatible with "negative" zoom (ie. shrinking the image). To
-  // keep things simple at first, I will do this by just skipping
-  // points (a smarter thing to do would be to average).
-
-  int row, col;             // column and row in the data file
-  int imgcol, imgrow;       // column and row in the image output file
-  int n, m;                 // repeat indices for col and row
-  int iw, ih;
-
-  iw = dozoom(w,xzoom);
-  ih = dozoom(h,yzoom);
-  
-  row = 0; n = 0;
-  while (row<h) // loop through rows (col = 0; col <h; col++)
-    {
-      if (yzoom < 0)
-       {
-         if (row%(-yzoom) != 0)
-           {
-             row++;
-             continue;
-           }
-         else imgrow = row/(-yzoom);
-       }
-      else imgrow = yzoom*row + n;
-      if (imgrow > ih-1) break;
-      
-      col = 0; m = 0;
-      while (col<w) // now loop through columns
-       {
-         if (xzoom < 0)
-           {
-             if (col%(-xzoom) != 0)
-               {
-                 col++;
-                 continue;
-               }
-             else imgcol = col/(-xzoom);
-           }
-         else imgcol = xzoom*col + m;
-         if (imgcol > iw-1) break;
-
-         // Now actually decide on a color for the pixel
-
-         unsigned char r,g,b;
-         getrgb(row,col,r,g,b);
-
-         image[3*imgrow*iw+3*imgcol] = r;
-         image[3*imgrow*iw+3*imgcol+1] = g;
-         image[3*imgrow*iw+3*imgcol+2] = b;
-
-         if (3*imgrow*iw+3*imgcol+2 > dozoom(w,xzoom)*dozoom(h,yzoom)*3)
-           {
-             warn( "row %d col %d n %d m %d ir %d ic %d iw %d ih %d iw*ih*3 %d over bounds %d > %d\n", 
-                     row, col, n, m, imgrow, imgcol, iw, ih, iw*ih*3, 3*imgrow*iw+3*imgcol+2, 
-                     dozoom(w,xzoom)*dozoom(h,yzoom)*3);
-             exit(-1);
-           }
-         if (xzoom < 0 || m == xzoom-1)
-           {
-             m=0; col++; 
-             if (col == w) break; 
-             else continue;
-           }
-         else
-           {
-             m++; continue; 
-           }
-       }
-      
-      if (yzoom < 0 || n == yzoom-1)
-       {
-         n=0; row++; 
-         if (row == h) break;
-         else continue;
-       }
-      else 
-       {
-         n++; continue;
-       }
-    }
-
-  fl_draw_image(image, ox, oy, iw, ih, 3, 0);
-  if(zoom_window)
-    zoom_window->redraw();
-}
-
-void ImageWindow::draw_overlay() 
-{
-  if (pfc.hide_data->value())
-    fl_rectf(0,0,dozoom(w,xzoom),dozoom(h,yzoom),0,0,0);
-
-  imageprinter->updatePreview();
-  if (line_cut_type)
-    {
-      fl_color(FL_RED);
-      if (line_cut_type == HORZLINE)
-       fl_line(dozoom(w,xzoom),dozoom(line_cut_yp,yzoom)+dozoom(1,yzoom)/2,
-               0,dozoom(line_cut_yp,yzoom)+dozoom(1,yzoom)/2);
-      else if (line_cut_type == VERTLINE)
-       fl_line(dozoom(line_cut_xp,xzoom)+dozoom(xzoom,1)/2,0,
-               dozoom(line_cut_xp,xzoom)+dozoom(xzoom,1)/2,dozoom(h,yzoom));
-      else if (line_cut_type == OTHERLINE)
-       fl_line(dozoom(lcx1,xzoom)+dozoom(1,xzoom)/2, 
-               dozoom(lcy1,yzoom)+dozoom(1,yzoom)/2, 
-               dozoom(lcx2,xzoom)+dozoom(1,xzoom)/2, 
-               dozoom(lcy2,yzoom)+dozoom(1,yzoom)/2);
-    }
-
-  if((zoom_window && zoom_window->visible()) || (zoomWindowDragging))
-    {
-      fl_color(FL_GREEN);
-      if(!zoomWindowDragging)
-       zoom_window->getSourceArea(zwd_x1,zwd_y1,zwd_x2,zwd_y2);
-      int x2off = (xzoom > 0) ? 1 : 0;
-      int y2off = (yzoom > 0) ? 1 : 0;
-      fl_line(dozoom(zwd_x1,xzoom), 
-             dozoom(zwd_y1,yzoom), 
-             dozoom(zwd_x2,xzoom)-x2off, 
-             dozoom(zwd_y1,yzoom));
-      fl_line(dozoom(zwd_x2,xzoom)-x2off, 
-             dozoom(zwd_y1,yzoom), 
-             dozoom(zwd_x2,xzoom)-x2off, 
-             dozoom(zwd_y2,yzoom)-y2off);
-      fl_line(dozoom(zwd_x2,xzoom)-x2off, 
-             dozoom(zwd_y2,yzoom)-y2off, 
-             dozoom(zwd_x1,xzoom), 
-             dozoom(zwd_y2,yzoom)-y2off);
-      fl_line(dozoom(zwd_x1,xzoom), 
-             dozoom(zwd_y2,yzoom)-y2off, 
-             dozoom(zwd_x1,xzoom), 
-             dozoom(zwd_y1,yzoom));
-    }
-
-  if(pf->peaks != NULL && (pfc.plot_peaks->value() || pfc.plot_valleys->value()))
-    {
-        for (int j=0; j<h; j++)
-       {
-         for (int i=0; i<w; i++)
-           {
-             if (i>=pf->w || j>=pf->h)
-               // So that we can plot peaks from previous IP settings
-               // on top of current data without a segfault
-               continue;
-             if (pf->peaks[j*w+i] == 1 && pfc.plot_peaks->value())
-               draw_overlay_pixel(i,j,pfc.peak_color_box->color());
-             else if (pf->peaks[j*w+i] == -1 && pfc.plot_valleys->value())
-               draw_overlay_pixel(i,j,pfc.valley_color_box->color());
-           }
-       }
-    }
-
-  for(modules_t::iterator i = modules.begin(); i != modules.end(); i++)
-    (*i)->overlay_callback();
-}
-
-void ImageWindow::draw_overlay_pixel(int i, int j, Fl_Color color)
-{
-  int rw = (xzoom < 0) ? 1 : xzoom;
-  int rh = (yzoom < 0) ? 1 : yzoom;
-  fl_color(color);
-  fl_rectf(dozoom(i,xzoom), dozoom(j,yzoom), rw, rh);
-}
-
-void ImageWindow::draw_overlay_pixel(int i, int j, uchar r, uchar g, uchar b)
-{
-  int rw = (xzoom < 0) ? 1 : xzoom;
-  int rh = (yzoom < 0) ? 1 : yzoom;
-  fl_color(r,g,b);
-  fl_rectf(dozoom(i,xzoom), dozoom(j,yzoom), rw, rh);
-}
-
-void ImageWindow::makeZoomWindow()
-{
-  if(zoom_window == NULL)
-    {      
-      zoom_window = new ZoomWindow(dozoom(w,xzoom)/5,dozoom(h,yzoom)/5); // *.1 * 2 = /5, 10% of image size (default zoom is 2)
-      zoom_window->img = this;
-      zoom_window->size_range(1,1);
-      if (xzoom > 1) zoom_window->xscale *= xzoom;
-      if (yzoom > 1) zoom_window->yscale *= yzoom;
-    }
-}
-void ImageWindow::showZoomWindow(bool toggle)
-{
-  makeZoomWindow();
-  if(zoom_window->visible() && toggle)
-    zoom_window->hide();
-  else
-    zoom_window->show();
-}
-
-// Helper function for the middle-shift button below.
-inline static double distance_squared(double x1, double y1, double x2, double y2)
-{
-  x1 -= x2;
-  y1 -= y2;
-  return x1*x1+y1*y1;
-}
-
-// Check to see if (x1,y1) is closer to (x2,y2) than squared-distance distance.  If it is, update
-// distance to the distance between them, and set zoomWindowDragging to zw
-// Helper function for the middle-shift button below.
-void ImageWindow::tryZoomCorner(int x1, int y1, int x2, int y2, zoomWindowDragging_t zw, double &dist)
-{
-  double nd = distance_squared(x1,y1,x2,y2);
-  if(nd < dist)
-    {
-      dist = nd;
-      zoomWindowDragging = zw;
-    }
-}
-
-// adapted from from http://www.cpp-programming.net/c-tidbits/gettimeofday-function-for-windows/
-double current_time()
-{
-  struct timeval stop;
-#ifndef WIN32
-  gettimeofday(&stop, NULL);
-#else
-  FILETIME ft;
-  unsigned __int64 tmpres = 0;
-  GetSystemTimeAsFileTime(&ft);
-  tmpres |= ft.dwHighDateTime;
-  tmpres <<= 32;
-  tmpres |= ft.dwLowDateTime;
-  /*converting file time to unix epoch*/
-  tmpres /= 10;  /*convert into microseconds*/
-  tmpres -= DELTA_EPOCH_IN_MICROSECS;
-  stop.tv_sec = (long)(tmpres / 1000000UL);
-  stop.tv_usec = (long)(tmpres % 1000000UL);
-#endif
-  double time = (((double)(stop.tv_sec)) + ((double)(stop.tv_usec) * 1e-6));
-  if (!isnormal(time))
-    info("time %e sec %d usec %d\n", time, stop.tv_sec, stop.tv_usec);
-  return time;
-}
-
-int ImageWindow::handle(int event) 
-{
-  static double lastFocus = 0; // Time when we got the focus, or NAN if we don't have the focus.
-  static double t0Focus = current_time(); // Just a handy offset for debug messages
-  static bool hungryFocus = false;  // If this is true, we're eating push/drag events because this was the click that focused the mouse.
-  static bool inFocus = false; // This is set to true when we get a focus event
-  //if (event == FL_ENTER)
-  // info("got FL_ENTER\n");
-  //if (event == FL_MOVE)
-  //  info("got FL_MOVE\n");
-  //Fl_Window::handle() was stealing our FL_ENTER and FL_MOVE events
-  //if (Fl_Window::handle(event)) return 1;
-
-  for(modules_t::iterator i = modules.begin(); i != modules.end(); i++)
-    {
-      int r = (*i)->event_callback(event);
-      if(r)
-       return r;
-    }
-
-  int n;
-  int button = Fl::event_button();
-  
-  if ((button == 3) && (Fl::event_state() & FL_ALT))
-    button = 2;
-  switch (event)
-    {
-      // Drag and drop
-    case FL_DND_ENTER:          // return(1) for these events to 'accept' dnd
-    case FL_DND_DRAG:
-    case FL_DND_RELEASE:
-      return(1);
-    case FL_PASTE:              // handle actual drop (paste) operation
-      (*drag_n_drop)(Fl::event_text());
-      return(1);
-    case FL_SHOW:
-      // Use a cross cursor                                
-      cursor(FL_CURSOR_CROSS);
-      break;
-    case FL_KEYUP:
-      n = Fl::event_key();
-      if(statusCallback)
-       statusCallback(n,false);
-      break;
-    case FL_KEYDOWN:      
-      n = Fl::event_key();
-      if(statusCallback)
-       statusCallback(n,true);
-      switch(n)
-       {       
-//     case 'd':
-//       dumpColormap();
-//       return 1;
-       case 's':
-         switch(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT))
-           {
-           case FL_ALT:
-             // Snap the window size to the actual image size
-             size(dozoom(w,xzoom), dozoom(h,yzoom));
-             return 1;
-           case FL_CTRL:
-             if(zoom_window)
-               {
-                 zoom_window->autonormalize = !zoom_window->autonormalize;
-                 return 1;
-               }
-              // Falling case                                      
-           case FL_SHIFT:
-             normalizeOnZoom();
-             return 1;
-           }
-         break;
-       case 'z':
-         if (Fl::event_state() & FL_CTRL)
-           exportMTX(false, true);
-         else 
-           showZoomWindow(true);
-         return 1;
-         break;
-       case '.':
-         if (Fl::event_state() & FL_SHIFT)
-           {
-             setXZoom(xzoom+1);
-             damage(FL_DAMAGE_ALL);          
-           }
-         else if (Fl::event_state() & FL_CTRL)
-           {
-             setYZoom(yzoom+1);
-             damage(FL_DAMAGE_ALL);
-             
-           }
-         else 
-           {
-             setXZoom(xzoom+1); 
-             setYZoom(yzoom+1);
-             damage(FL_DAMAGE_ALL);
-           }
-         return 1;
-       case ',':
-         if (Fl::event_state() & FL_SHIFT)
-           {
-             setXZoom(xzoom-1);
-             damage(FL_DAMAGE_ALL);
-           }
-            
-         else if (Fl::event_state() & FL_CTRL)
-           {
-             setYZoom(yzoom-1);
-             damage(FL_DAMAGE_ALL);
-             
-           }
-         else 
-           {
-             setXZoom(xzoom-1); 
-             setYZoom(yzoom-1);
-             damage(FL_DAMAGE_ALL);
-           }
-         return 1;
-       case '1':
-         if (Fl::event_state() & FL_SHIFT)
-           (xzoom > yzoom) ? setXZoom(yzoom) : setYZoom(xzoom);
-         else
-           (xzoom > yzoom) ? setYZoom(xzoom) : setXZoom(yzoom);
-         damage(FL_DAMAGE_ALL);
-         return 1;
-//     case 'i':
-//       invert = !invert;
-//       plotCmap();
-//       redraw();
-//       colormap_window->update();
-//       if (external_update != NULL)
-//         (*external_update)();
-//       return 1;
-//     case 'h':
-//       plot_hist = !plot_hist;
-//       plotHist();
-//       if (external_update != NULL)
-//         (*external_update)();
-//       return 1;
-       default:
-         if(isalpha(n))
-           {
-             char buf[4096];
-             const char *cmd = getenv("SPYVIEW_EXTERNAL");
-             if(cmd == NULL)
-               break;
-             int ix = get_event_x();
-             int iy = get_event_y();
-             snprintf(buf,sizeof(buf),"%s %c %g %g %d %d", cmd, n, id.getX(ix), id.getY(iy),ix, iy);
-             int res = system(buf);
-             if(res == -1)
-               warn("Unable to run command: \"%s\": %s\n",buf, strerror(errno));
-             if(res == 0)
-               {
-                 info("Reloading: \"%s\"\n",filename.c_str());
-                 string s = filename;           // We copy here because loadData nukes filename right away.
-                 loadData(s.c_str());
-               }
-           }
-         break;
-
-       }    
-      break;
-
-    case FL_MOVE:
-      if(statusCallback)
-       statusCallback(-1,true);
-      break;
-
-    case FL_FOCUS:
-      lastFocus = current_time();
-      inFocus = true;
-      //info("focus event time %g\n", lastFocus);
-      //fprintf(stderr,"recieved focus %g time %g t0 %g\n",lastFocus-t0Focus, lastFocus, t0Focus);
-      return Fl_Overlay_Window::handle(event);
-
-    case FL_UNFOCUS:
-      lastFocus = NAN;
-      inFocus = false;
-      //fprintf(stderr,"Defocus %g at time %g t0 %g\n",current_time()-t0Focus, current_time(), t0Focus);
-      return Fl_Overlay_Window::handle(event);
-
-/* Focus logic:
-   When we are focused, ignore the *FIRST* mouse click if it occurs within 50 ms of becoming focused.  This way, if the user
-     focuses the window with a non-mouse click action (alt-tab), we're in good shape as long as they're not *really* fast.  In
-     practice, I usually see the click event comes within a few microseconds (!) of the focus event (under wine)
-   If we ignored a click, ignore follow-up drag and release events, unless the user keeps the button down for at least
-     one second.  If they do, assume they're frustrated and give in.
-   If we get a click when unfocused, assume it's an immediate prelude to being focused and treat it as a click within 50ms of
-     getting focused.  This never seems to happen (under my WM in Linux and wine.  Probably smart to leave the logic in)
-*/
-
-    case FL_PUSH:
-      if(isnan(lastFocus) && stupid_windows_focus)
-       {
-         fprintf(stderr,"Ate unfocused click.  This apparently never happens.\n");       
-         hungryFocus = true;
-         lastFocus = current_time();
-         return Fl_Overlay_Window::handle(event);
-       }
-      // Warning: you can have an unfocused drag or release under linux; we shouldn't eat these!
-      // For this reason, we will only eat things if we are in focus
-    case FL_DRAG: // Falling case!
-    case FL_RELEASE:
-
-      // For FL_DRAG, we cannot rely on Fl::event_button() (although
-      // it seems to work on unix) I don't know why I can't replace
-      // the Fl::event_buttion() above with this, but if I do, the
-      // zoom window stops working...
-      if (Fl::event_state() & FL_BUTTON1)
-       button = 1;
-      else if (Fl::event_state() & FL_BUTTON2)
-       button = 2;
-      else if (Fl::event_state() & FL_BUTTON3)
-       {
-         if (Fl::event_state() & FL_ALT)
-           button = 2;
-         else 
-           button = 3;
-       }
-      // Let's only eat a non-modified button 1 click
-      if(stupid_windows_focus && (button == 1) && !(Fl::event_state() & FL_SHIFT) && !(Fl::event_state() & FL_CTRL)) 
-       {
-         if (hungryFocus)
-           {
-             if (inFocus)
-               {
-                 if(event == FL_RELEASE || (current_time() - lastFocus >= 0.1))
-                   {
-                     //fprintf(stderr,"Focus eating is done (100 ms after initial click) %g\n",current_time()-lastFocus);
-                     lastFocus = 0;
-                     hungryFocus = false;
-                     return Fl_Overlay_Window::handle(event);
-                   }
-                 else
-                   {
-                     fprintf(stderr,"Ate drag/release event, t<100 ms after focus click %g\n",current_time()-lastFocus);
-                     return Fl_Overlay_Window::handle(event);
-                   }
-               }
-           }
-         else if ((current_time() - lastFocus < 0.05))
-           {
-             //fprintf(stderr,"Ate initial click (%g) last %g t0 %g\n",lastFocus-t0Focus, lastFocus, t0Focus);
-             hungryFocus = true;
-             return Fl_Overlay_Window::handle(event);
-           }
-       }
-
-      if(statusCallback)
-       statusCallback(-1,true);
-
-      int state = Fl::event_state();
-      int tmp;
-      double d1,d2;
-      if (none(state) || alt(state)) // horz/vert LC
-       switch(button)
-         {
-         case 1:
-           tmp = get_event_y();
-           if (tmp > h-1)
-             tmp = h-1;
-           if (line_cut_yp < 0)
-             tmp = 0;
-           if (line_cut_yp == tmp && line_cut_type == HORZLINE)
-             return 1;
-           if(!(line_cut_limit & HORZLINE))
-             return 1;
-           line_cut_yp = tmp;
-           line_cut_type = HORZLINE;
-           plotLineCut();
-           redraw_overlay();
-           return 1;
-         case 3:
-           if(!alt(state))
-             break; // Right-alt is vertical, but not right-unshifted.
-         case 2:         
-           tmp = get_event_x();
-           if (tmp > w-1)
-             tmp = w-1;
-           if (tmp < 0)
-             tmp = 0;
-           if (line_cut_xp == tmp && line_cut_type == VERTLINE) return 1;
-           if(!(line_cut_limit & VERTLINE))
-             return 1;
-           line_cut_xp = tmp;
-           line_cut_type = VERTLINE;
-           plotLineCut();
-           redraw_overlay();
-           return 1;
-         default: 
-           return Fl_Overlay_Window::handle(event);
-         }
-      else if (shift(state)) // zoom windows (this is a long one)
-       switch(button)
-       {
-       case 1:
-         switch(event)
-           {
-           case FL_PUSH:
-             zwd_x1 = get_event_x();
-             zwd_y1 = get_event_y();
-             zwd_x2 = zwd_x1;
-             zwd_y2 = zwd_y1;
-             zoomWindowDragging = ZOOM_DRAG;
-             break;
-           case FL_RELEASE:
-             zwd_x2 = get_event_x();
-             zwd_y2 = get_event_y();
-             makeZoomWindow();
-             zoom_window->center_x = (zwd_x1+zwd_x2)/2;
-             zoom_window->center_y = (zwd_y1+zwd_y2)/2;
-             zoom_window->size((abs(zwd_x2-zwd_x1))*zoom_window->xscale, (abs(zwd_y2-zwd_y1))*zoom_window->yscale);
-             showZoomWindow();
-             zoom_window->zoomMoved();
-             zoomWindowDragging = ZOOM_NO;
-             break;
-           case FL_DRAG:
-             zwd_x2 = get_event_x();
-             zwd_y2 = get_event_y();
-             redraw_overlay();
-             break;
-           }
-         break;
-       case 2:
-         if(zoom_window == NULL)
-           return 1;
-         switch(event)
-           {
-           case FL_PUSH:
-             {
-               int mx1 = get_event_x();
-               int my1 = get_event_y();
-               zoom_window->getSourceArea(zwd_x1,zwd_y1,zwd_x2,zwd_y2);
-               zoomWindowDragging = ZOOM_RESIZE_NW;
-               double distance = distance_squared(mx1,my1, zwd_x1,zwd_y1);
-               tryZoomCorner(mx1,my1,zwd_x1,zwd_y2,ZOOM_RESIZE_SW,distance);
-               tryZoomCorner(mx1,my1,zwd_x2,zwd_y1,ZOOM_RESIZE_NE,distance);
-               tryZoomCorner(mx1,my1,zwd_x2,zwd_y2,ZOOM_RESIZE_SE,distance);
-             } // Warning!  Falling case!              
-           case FL_DRAG:
-             {
-               switch(zoomWindowDragging)
-                 {
-                 case ZOOM_RESIZE_NW:  zwd_x1 = get_event_x(); zwd_y1 = get_event_y(); break;
-                 case ZOOM_RESIZE_SW:  zwd_x1 = get_event_x(); zwd_y2 = get_event_y(); break;
-                 case ZOOM_RESIZE_NE:  zwd_x2 = get_event_x(); zwd_y1 = get_event_y(); break;
-                 case ZOOM_RESIZE_SE:  zwd_x2 = get_event_x(); zwd_y2 = get_event_y(); break;
-                 case ZOOM_NO: case ZOOM_DRAG: info("Unusual event; hard to get here.\n"); break;
-                 }
-               redraw_overlay();
-               return 1;
-             }           
-           case FL_RELEASE:
-             switch(zoomWindowDragging)
-               {
-               case ZOOM_RESIZE_NW:  zwd_x1 = get_event_x(); zwd_y1 = get_event_y(); break;
-               case ZOOM_RESIZE_SW:  zwd_x1 = get_event_x(); zwd_y2 = get_event_y(); break;
-               case ZOOM_RESIZE_NE:  zwd_x2 = get_event_x(); zwd_y1 = get_event_y(); break;
-               case ZOOM_RESIZE_SE:  zwd_x2 = get_event_x(); zwd_y2 = get_event_y(); break;
-               case ZOOM_NO: case ZOOM_DRAG: info("Unusual event; hard to get here.\n"); break;
-               }
-             zoom_window->center_x = (zwd_x1+zwd_x2)/2;
-             zoom_window->center_y = (zwd_y1+zwd_y2)/2;
-             zoom_window->size((abs(zwd_x2-zwd_x1))*zoom_window->xscale, (abs(zwd_y2-zwd_y1))*zoom_window->yscale);
-             showZoomWindow();
-             zoomWindowDragging = ZOOM_NO;
-             zoom_window->zoomMoved();
-             return 1;
-           }
-         break;
-       case 3:
-         showZoomWindow();
-         zoom_window->center_x = get_event_x();
-         zoom_window->center_y = get_event_y();
-         zoom_window->zoomMoved();
-         return 1;
-       default: 
-         return Fl_Overlay_Window::handle(event);
-       }
-      else if (ctrl(state))  // arb LC
-       switch (button)
-         {
-         case 1:
-           if (event == FL_PUSH)
-             {
-               lcx1 = lcx2 = get_event_x();
-               lcy1 = lcy2 = get_event_y();
-               line_cut_type = OTHERLINE;
-               redraw_overlay();
-               return 1;
-             }
-           else //if (event == FL_DRAG) // Button 1 + control + drag (arb line cut)
-             {
-               lcx2 = get_event_x();
-               lcy2 = get_event_y();
-               if (lcx2 < 0) lcx2 = 0;
-               if (lcy2 < 0) lcy2 = 0;
-               if (lcx2 > w-1) lcx2 = w-1;
-               if (lcy2 > h-1) lcy2 = h-1;
-               plotLineCut();
-               redraw_overlay();
-               return 1;
-             }
-         case 2:
-           static int pointnum = 0;
-           int nx, ny;
-           nx = get_event_x();
-           ny = get_event_y();
-           if (nx < 0) nx = 0;
-           if (ny < 0) ny = 0;
-           if (nx > w-1) nx = w-1;
-           if (ny > h-1) ny = h-1;
-           d1 = sqrt(static_cast<double>((nx-lcx1)*(nx-lcx1)+(ny-lcy1)*(ny-lcy1)));
-           d2 = sqrt(static_cast<double>((nx-lcx2)*(nx-lcx2)+(ny-lcy2)*(ny-lcy2)));
-           if (event == FL_PUSH)
-             {
-               if (d1 < d2)
-                 { lcx1 = nx; lcy1 = ny; pointnum = 1;}
-               else
-                 { lcx2 = nx; lcy2 = ny; pointnum = 2;}
-             }
-           else if (event == FL_DRAG)
-             {
-               if (pointnum == 1)
-                 { lcx1 = nx; lcy1 = ny; }
-               else if (pointnum == 2)
-                 { lcx2 = nx; lcy2 = ny; }
-             }
-           plotLineCut();
-           redraw_overlay();
-           return 1;
-         case 3:
-           static int x0, y0, x1, y1; // Mouse coord at push and then at drag
-           static int lcx1i, lcy1i, lcx2i, lcy2i; // Initial line endpoint on the push
-           int dx, dy; // displacments
-           if (event == FL_PUSH) // Pushing button 3 + control (arb line cut)
-             {
-               if(!(line_cut_limit & OTHERLINE))
-                 return 1;
-               x0 = get_event_x();
-               y0 = get_event_y();
-               lcx1i = lcx1;
-               lcx2i = lcx2;
-               lcy1i = lcy1;
-               lcy2i = lcy2;
-               line_cut_type = OTHERLINE;
-               return 1;
-             }
-           else if (event == FL_DRAG) // Dragging button 3 + control (arb line cut)
-             {
-               x1 = get_event_x();
-               y1 = get_event_y();
-               dx = x1-x0;
-               dy = y1-y0;
-               if (lcx1i+dx < 0) dx = -lcx1i;
-               if (lcx1i+dx > w-1) dx = w-1-lcx1i;
-               if (lcx2i+dx < 0) dx = -lcx2i;
-               if (lcx2i+dx > w-1) dx = w-1-lcx2i;
-               if (lcy1i+dy < 0) dy = -lcy1i;
-               if (lcy1i+dy > h-1) dy = h-1-lcy1i;
-               if (lcy2i+dy < 0) dy = -lcy2i;
-               if (lcy2i+dy > h-1) dy = h-1-lcy2i;
-               if (dx == 0 && dy == 0 && line_cut_type == OTHERLINE) return 1;
-               lcx1 = lcx1i + dx; lcx2 = lcx2i + dx;
-               lcy1 = lcy1i + dy; lcy2 = lcy2i + dy;
-               line_cut_type = OTHERLINE;
-               plotLineCut();
-               redraw_overlay();
-               return 1;
-             }
-         default: 
-           return Fl_Overlay_Window::handle(event);
-         }
-      // no modifiers, or multiple modifiers...
-      if (button == 3 && controls_window != NULL && event == FL_PUSH)
-       {
-         if (controls_window->visible())
-           controls_window->hide();
-         else
-           controls_window->show();
-         return 1;
-       }
-      break;
-    }
-  return 0;
-}
-
-double ImageWindow::dataval(int x, int y)
-{
-  if (x>=0 && x<w && y>=0 && y<h)
-    return id.raw(x,y) - ((plane) ? id.quant_to_raw(planeval(y,x)) : 0); // watchout: planeval is swapped i,j!
-  else 
-    return 0;
-}
-  
-
-static void swap_crossection(const char *xsection_fn, const char *xsection_tmp_fn)
-{
-#ifdef WIN32
-  if(unlink(xsection_fn) != 0)
-    {
-      info("Error deleting temporary file \"%s\": %s\n", xsection_fn,strerror(errno));
-      // Sometimes, win32 seems to have trouble delete files: probably due to stupid locking...
-      // In this case, we will try again with a new filename
-//       int n=0;
-//       while (true)
-//     {
-//       make_tmpfiles();
-//       info("Trying new temporary filename %s", xsection_fn);
-//       if (fopen(xsection_fn, "w") != NULL)
-//         return;
-//       sleep(5);
-//       n++;
-//       if (n==10)
-//         {
-//           info("giving up on xsection file!");
-//           return;
-//         }
-    }
-#endif
-  if(rename(xsection_tmp_fn, xsection_fn) != 0)
-    {
-      info("Error renaming temporary \"%s\" to \"%s\": %s\n",
-          xsection_tmp_fn, xsection_fn, strerror(errno));
-      return;
-    }
-}
-
-
-
-void ImageWindow::plotLineCut(bool nothrottle)
-{
-  static OptThrottle<ImageWindow> throttle(this,&ImageWindow::plotLineCut);
-  if(!(nothrottle || throttle.throttle()))
-    return;
-
-  FILE *fp;
-  if (line_cut_type == NOLINE)
-    {
-      if (gplinecut.isopen())
-       {
-         // set term x11 close doesn't work if the terminal type is not wxt.
-         // Newer versions of gnuplot default to wxt.
-         // Safer to kill gnuplot; of course, this "forgets" where the window was.
-         gplinecut.close();
-       }
-      return;
-    }
-  
-  if (!gplinecut.isopen())
-    {
-      gplinecut.open();
-      if(!gplinecut.open())
-       {
-         nognuplot();
-         return;
-       }
-      gplinecut.cmd("set style data %s\n", gp_with_string.c_str());
-    }
-
-  if ((fp = fopen(xsection_fn, "w")) == NULL)
-    {
-      error("Error opening file \"%s\": %s\n", xsection_tmp_fn, strerror(errno));
-      
-      return;
-    }
-  unlink("xsection.dat"); 
-#ifdef HAVE_SYMLINK
-// just so that we always have a file in the current dir where we can easily access the data
-  if(symlink(xsection_fn, "xsection.dat") != 0) 
-    fprintf(stderr,"Error creating xsection.dat symlink: %s\n",strerror(errno));
-#endif
-
-  // OK, let's give this a real cleanup.
-  // We will plot the real, unquantized raw data, with as little permutation as possible.  
-
-  double xstep;
-  double ystep;
-  string axname;
-  int x1,x2,y1,y2;
-  double ax1, ax2;
-
-  int npeaks = 0;
-  int  nvalleys = 0;
-  double peak, valley;
-
-  if (line_cut_type == HORZLINE)
-    {
-      int j = line_cut_yp;
-      for (int i=0; i < w; i++)
-       {
-         fprintf(fp, "%e %e ", id.getX(i), dataval(i,j));
-         if (pf->peaks != NULL && pfc.plot_peaks->value() && pf->peaks[j*w+i] == 1)
-           {
-             npeaks++;
-             fprintf(fp, "%e ",  dataval(i,j));
-           }
-         else fprintf(fp, "none ");
-         if (pf->peaks != NULL && pfc.plot_valleys->value() && pf->peaks[j*w+i] == -1)
-           {
-             nvalleys++;
-             fprintf(fp, "%e\n",  dataval(i,j));
-           }
-         else fprintf(fp, "none\n");
-       }
-      x1 = 0; x2 = w; 
-      y1 = y2 = line_cut_yp;
-      axname = id.xname;
-      ax1 = id.getX(x1);
-      ax2 = id.getX(x2);
-    }
-  else if (line_cut_type == VERTLINE)
-    { 
-      int i = line_cut_xp;
-      for (int j=0; j < h; j++)
-       {
-         fprintf(fp, "%e %e ", id.getY(j), dataval(i,j));
-         if (pf->peaks != NULL && pfc.plot_peaks->value() && pf->peaks[j*w+i] == 1)
-           {
-             npeaks++;
-             fprintf(fp, "%e ",  dataval(i,j));
-           }
-         else fprintf(fp, "none ");
-         if (pf->peaks != NULL && pfc.plot_valleys->value() && pf->peaks[j*w+i] == -1)
-           {
-             nvalleys++;
-             fprintf(fp, "%e\n",  dataval(i,j));
-           }
-         else fprintf(fp, "none\n");
-       }
-      x1 = x2 = line_cut_xp; 
-      y1 = h; y2 = 0; 
-      axname= id.yname;
-      ax1 = id.getY(y1);
-      ax2 = id.getY(y2);
-    }
-  else // otherwise, we'll use bilinear interpolation
-    { 
-      int num_steps, n;
-      x1 = lcx1; x2 = lcx2; 
-      y1 = lcy1; y2 = lcy2; 
-      
-      if (x1 == x2 && y1 == y2) return;
-
-      double i,j;
-      double i1,j1;
-      double i2,j2;
-      double d1,d2,d;
-      double x;
-      bool step_x;
-      
-      if (abs(x2-x1) > abs(y2-y1))
-       { 
-         step_x = true;
-         num_steps = abs(x2-x1); 
-         xstep = 1.0*(x2-x1)/num_steps; 
-         ystep = 1.0*(y2-y1)/num_steps;  
-       }
-      else 
-       { 
-         step_x = false;
-         num_steps = abs(y2-y1); 
-         ystep = 1.0*(y2-y1)/num_steps; 
-         xstep = 1.0*(x2-x1)/num_steps; 
-       }
-
-      i = x1; j = y1;
-      for (n=0; n<num_steps; n++)
-       {
-         i1 = floor(i);
-         i2 = ceil(i);
-         j1 = floor(j);
-         j2 = ceil(j);
-         if (i1 == i2 && j1 == j2)
-           d = dataval(i1,j1);
-         else if (step_x)
-           {
-             d1 = dataval(i1, j1);
-             d2 = dataval(i1, j2);
-             d = d1 + (d2-d1)*(j-j1);
-           }
-         else 
-           {
-             d1 = dataval(i1, j1);
-             d2 = dataval(i2, j1);
-             d = d1 + (d2-d1)*(i-i1);
-           }
-         if (lc_axis == XAXIS) x = id.getX(i);
-         else if (lc_axis == YAXIS) x = id.getY(j);
-         else
-           {
-             d1 = id.getX(i)-id.getX(x1);
-             d2 = id.getY(j)-id.getY(y1);
-             x = sqrt(d1*d1+d2*d2);
-           }
-         if (n == 0) ax1 = x;
-         if (n == num_steps-1) ax2 = x;
-         fprintf(fp, "%e %e\n", (double) x, d);
-         i+=xstep; j+=ystep;
-       }
-      if (lc_axis == XAXIS) axname = id.xname; 
-      else if (lc_axis == YAXIS) axname = id.yname; 
-      else axname = "Distance (" + id.xname + ")"; 
-    }
-
-  fprintf(fp, 
-         "#X axis: %s\n"
-         "#Line cut: %s %e to %e, %s %e to %e';\n"
-         "#Row %d %d Column %d %d'\n",
-         axname.c_str(), 
-         id.xname.c_str(), id.getX(x1), id.getX(x2), 
-         id.yname.c_str(), id.getY(y1), id.getY(y2),
-         x1, x2, y1, y2);
-         
-
-  fclose(fp);
-  //swap_crossection(xsection_fn, xsection_tmp_fn);
-  
-  //warn( "%e %e\n", ax1, ax2);
-
-  if (line_cut_xauto)
-    gplinecut.cmd("set xrange [%e:%e]\n",ax1, ax2);
-
-  for(modules_t::iterator i = modules.begin(); i != modules.end(); i++)
-    (*i)->linecut_callback(true);
-
-  char buf[1024];
-  gplinecut.cmd("set xlabel '%s';\n"
-               "set ylabel '%s';\n"
-               "set title \"%s \\n Line cut: %s %g to %g, %s %g to %g\";\n"
-               "plot '%s' u %s w %s t 'x %d %d y %d %d'",
-               axname.c_str(), 
-               id.zname.c_str(),
-               Gnuplot_Interface::escape(filename).c_str(), 
-               id.xname.c_str(), id.getX(x1), id.getX(x2), 
-               id.yname.c_str(), id.getY(y1), id.getY(y2),
-               xsection_fn, gp_using_string, gp_with_string.c_str(),
-               x1, x2, y1, y2);
-  if (npeaks != 0)
-    gplinecut.cmd(", '' u 1:3 w p pt 5 t 'Peaks'");
-  if (nvalleys != 0)
-    gplinecut.cmd(", '' u 1:4 w p pt 5 t 'Valleys'");
-  
-
-  for(modules_t::iterator i = modules.begin(); i != modules.end(); i++)
-    (*i)->linecut_callback(false);
-
-  gplinecut.cmd("\n");
-}
-
-void ImageWindow::plotCmap()
-{
-  static Throttle<ImageWindow> throttle(this,&ImageWindow::plotCmap);
-  if(!throttle.throttle())
-    return;
-  int i,j;
-  if (plot_cmap)
-    {
-      if (!gpcmap.isopen())
-       {
-         if(!gpcmap.open())
-           {
-             nognuplot();
-             return;
-           }
-       }
-      FILE *fp = fopen(cmap_fn, "w");
-      if (fp == NULL)
-       {
-         error("Error opening file \"%s\": %s\n", cmap_fn, strerror(errno));
-         return;
-       }
-      unlink("cmap.dat"); 
-#ifdef HAVE_SYMLINK
-      symlink(cmap_fn, "cmap.dat");
-#endif
-      for (i = 0; i < colormap_length; i++)
-       {
-         j = gammatable[i];
-         fprintf(fp, "%d %d %d %d\n", i ,colormap[3*j], colormap[3*j+1], colormap[3*j+2]);
-       }
-      fclose(fp);
-      gpcmap.cmd("set xrange [0:%d]; set yrange [0:255];"
-                "set data style linespoints; set nokey;\n", colormap_length);
-      gpcmap.cmd("plot '%s' u 1:2, '' u 1:3, '' u 1:4\n",cmap_fn);
-    }
-  else if (gpcmap.isopen())
-    gpcmap.close();
-}
-
-void ImageWindow::plotHist()
-{
-  static Throttle<ImageWindow> throttle(this,&ImageWindow::plotHist);
-  if(!throttle.throttle())
-    return;
-  int i, min, max, inc, bintotal;
-  if (plot_hist)
-    {
-      if(!gphist.isopen())
-       {
-         if(!gphist.open())
-           {
-             nognuplot();
-             return;
-           }
-       }
-      FILE *fp = fopen(hist_fn, "w");
-      if (fp == NULL)
-       {
-         error("Error opening file \"%s\": %s\n", hist_fn, strerror(errno));
-         return;
-       }
-      unlink("hist.dat"); 
-#ifdef HAVE_SYMLINK
-      symlink(hist_fn, "hist.dat");
-#endif
-      min = (hmin < datamin) ? hmin : datamin; 
-      max = (hmax > datamax) ? hmax : datamax;
-      inc = (datamax - datamin)/300; 
-      if (inc < 1) inc = 1;
-      bintotal=0;
-      for (i = min ; i < max+inc && i < 65535 ; i++)
-       {
-         bintotal += datahist[i];
-         if ( (i%inc) == 0)
-           {
-             fprintf(fp, "%d %e %d %d\n",i, id.quant_to_raw(i), bintotal, 
-                     ((hmax-inc>=i && hmax-inc<=(i+inc-1)) ? 1 : 0) + 
-                     ((hmin+inc>=i && hmin+inc<=(i+inc-1)) ? 1 : 0));
-             bintotal = 0;
-           }
-       }
-      fclose(fp);
-      gphist.cmd("set x2range [%d:%d]; set xrange [%e:%e]; "
-                "set x2tics; set yrange [1e-1:*];"
-                "set style data boxes; set style fill solid;\n"
-                "set nokey; set title '%s';"
-                "set xlabel '%s'; set x2label 'Gray Value'\n", 
-                min-3*inc, max+3*inc, id.quant_to_raw(min-3*inc), id.quant_to_raw(max+3*inc), hist_fn, id.zname.c_str());
-      gphist.cmd("plot '%s' u 1:4 ax x2y2 lt 2, '' u 1:3 ax x2y1 lt 1\n", hist_fn);
-    }
-  else if (gphist.isopen())
-    {
-      gphist.close();
-    }
-}
-      
-void ImageWindow::setMin(int m) 
-{
-  if (m > LMAX) m = LMAX;
-  if (m < 0) m = 0;
-  hmin = m;
-  if (hmax < hmin) 
-    hmin = hmax;
-}
-
-void ImageWindow::setMax(int m) 
-{
-  if (m > LMAX) m = LMAX;
-  if (m < 0) m = 0;
-  hmax = m;
-  if (hmin > hmax)
-    hmax = hmin;
-}
-
-void ImageWindow::allocateImage()
-{
-  int newsize=(dozoom(w,xzoom))*(dozoom(h,yzoom))*3;
-  zap(image);
-  image = new uchar [newsize];
-}
-
-  
-void ImageWindow::setXZoom(int xz)
-{
-  if (xz == 0 || xz == -1)
-    {
-      if (xzoom > xz) xzoom = -2;
-      else xzoom = 1;
-    }
-  else xzoom = xz;
-
-  allocateImage();
-  size(dozoom(w,xzoom), dozoom(h,yzoom)); 
-}
-
-void ImageWindow::setYZoom(int yz)
-{
-  if (yz == 0 || yz == -1)
-    {
-      if (yzoom > yz) yzoom = -2;
-      else yzoom = 1;
-    }
-  else yzoom = yz;
-
-  allocateImage();
-  size(dozoom(w,xzoom), dozoom(h,yzoom));
-}
-
-void ImageWindow::setColormap(uchar *cmap, int l)
-{
-  zap(colormap);
-  zap(gammatable);
-  colormap = new uchar[3*l];
-  gammatable = new int[l];
-  colormap_length = l;
-
-  
-  int min_index = cmap_min * l;
-  int max_index = cmap_max * l;
-  //warn( "min %f max %f\n", cmap_min, cmap_max);
-  //warn( "min index %d max index %d\n", min_index, max_index);
-
-  int i,j;
-  double r,g,b,h,s,v;
-  for (j=0; j < l; j++)
-    {
-      if (j < min_index) i = min_index;
-      else if (j > max_index) i = max_index;
-      else i = j;
-
-      r = cmap[3*i];
-      g = cmap[3*i+1];
-      b = cmap[3*i+2];
-
-      // This was kindof fun, but not all that useful...
-      if(fabs(colormap_rotation_angle) > 1e-3)
-       {
-         Fl_Color_Chooser::rgb2hsv(r,g,b,h,s,v);
-         h = (h+(colormap_rotation_angle+0.001)/360.0*6.0);  // avoid singularity at angles of 60 degrees (problem on win32)
-         h = h - 6.0*floor(h/6.0);
-         Fl_Color_Chooser::hsv2rgb(h,s,v,r,g,b);
-       }
-      
-      // Let's move all of this crap into the colormap loading routine,
-      // where it really belongs. This is really, really overdue.
-      if (negate) i = (colormap_length-1) - j;
-      else i = j;
-      
-      colormap[3*i] = (int) (invert) ? 255-r : r;
-      colormap[3*i+1] = (int) (invert) ? 255-g : g;
-      colormap[3*i+2] = (int) (invert) ? 255-b : b;
-    }
-
-  setGamma(gam, gcenter);
-  adjustHistogram();
-  plotCmap();
-  colormap_window->update();
-}
-
-void ImageWindow::setGamma(double g, double gc) 
-{
-  // Build a lookup table that maps our data 
-  gam = g;
-  gcenter = gc;
-  
-  // problem near 1.0...  in the end, for some reason this didn't
-  // always work (was still crashing in win32), so i configured the
-  // spyview gui so that you cannot set gc greater that 0.999
-  //if (gc > 0.999) gc = 0.999;
-
-  // function:
-  //  f3(x,a,b) = b - (x<=b) * b * ((b-x)/b)**(a)  + (x>=b) * (1-b) * ((x-b)/(1-b))**(a)
-
-  double x,val;
-  for (int i = 0; i<colormap_length; i++)
-    {
-      x = 1.0*i/(colormap_length-1)+1e-9;
-      val = gc + ((x<=gc) ? (-gc) * pow(((gc-x)/gc), g) : (1-gc) * pow((x-gc)/(1-gc), g));
-      if (val > 1.0) val = 1.0;
-      if (val < 0.0) val = 0.0;
-      int index = round((val * (colormap_length-1)));
-      if (index < 0) index = 0;
-      if (index >= colormap_length) index = colormap_length-1;
-      gammatable[i] = index;
-      //if (i==0 || i == colormap_length-1)
-      //info( "%03d %.3f %07.3f %03d ", i,val, val*(colormap_length-1),  gammatable[i]);
-    }
-  //info( "\n");
-  
-  calculateHistogram();
-  adjustHistogram();
-  redraw();
-  colormap_window->update();
-}
-
-// Calculate the data's histogram
-void ImageWindow::calculateHistogram()
-{
-  int d;
-
-  // Zero the histogram table
-  for (int i = 0; i <= LMAX; i++)
-    datahist[i] = 0;
-  
-  //warn( "data[2] = %d\n",data[2]);
-  for (int i=0; i<w*h; i++)    
-    {
-      d = data[i] - planeval(i/w,i%w);
-      if (d > LMAX)
-       d = LMAX;
-      if (d < 0) 
-       d = 0;
-      ++datahist[d];
-    }
-  for (datamin = 0; datamin <= LMAX; datamin++)
-    if (datahist[datamin]>0) break;
-  for (datamax = LMAX; datamax >= 0; datamax--)
-    if (datahist[datamax]>0) break;
-}
-
-// Adjust the lookup table for the image histogram mapping
-void ImageWindow::adjustHistogram() 
-{
-  int i;
-  double s; // Scale factor that takes us from hmin-hmax to 0...1
-  double w; // Width of output
-  for (i = 0; i < hmin; i++)
-    imagehist[i] = 0;
-  for (i = hmax+1; i <= LMAX; i++)
-    imagehist[i] = LMAX;
-  if (hmin == hmax)
-    {
-      if (hmin == 0) hmax++;
-      else hmin--;
-      external_update();
-    }              
-  s = 1.0/(hmax-hmin);
-  w = LMAX;;
-
-  // I forgot that the gamma mapping is actually applied here on the 16 bit data!!!
-
-  for (i = hmin; i <= hmax; i++)
-    {
-      double d = (i-hmin)*s + 1e-9; // Put ourselves in the range 0...1
-      //d = pow(d,gam); // Apply our gamma correction
-      d = gcenter + ((d<=gcenter) ? 
-                    (-gcenter) * pow(((gcenter-d)/gcenter), gam) : 
-                    (1-gcenter) * pow((d-gcenter)/(1-gcenter), gam));
-      imagehist[i] = static_cast<int>(round(d*w));
-    }
-
-  // Drawing the window when it wasn't shown resulted in a flaky window manager placement problem!
-  if (shown())
-    redraw();
-}
-
-void ImageWindow::normalize() 
-{
-  int new_hmax, new_hmin;
-  int nwhite, nblack;
-  nblack = nwhite = 0;
-  calculateHistogram();
-  for ( new_hmin = 0; new_hmin <= LMAX; new_hmin++)
-    {
-      nblack += datahist[new_hmin];
-      if (nblack > bpercent*w*h/100) break;
-    }
-  for ( new_hmax = LMAX; new_hmax >= 0; new_hmax--)
-    {
-      nwhite += datahist[new_hmax];
-      if (nwhite > wpercent*w*h/100) break;
-    }
-  //setGamma(1.0);
-  setMin(new_hmin);
-  setMax(new_hmax);
-  adjustHistogram();
-}
-
-void ImageWindow::normalizeOnZoom() 
-{
-  if(!zoom_window)
-    return;
-  int new_hmax, new_hmin;
-  int nwhite, nblack;
-  int x1, y1, x2, y2;
-  zoom_window->getSourceArea(x1,y1,x2,y2);
-  int s = (x2-x1)*(y2-y1);
-  nblack = nwhite = 0;
-  zoom_window->calculateHistogram();
-  for ( new_hmin = 0; new_hmin <= LMAX; new_hmin++)
-    {
-      nblack += zoom_window->histogram[new_hmin];
-      if (nblack > bpercent*s/100) break;
-    }
-  for ( new_hmax = LMAX; new_hmax >= 0; new_hmax--)
-    {
-      nwhite += zoom_window->histogram[new_hmax];
-      if (nwhite > wpercent*s/100) break;
-    }
-  //setGamma(1.0);
-  setMin(new_hmin);
-  setMax(new_hmax);
-  adjustHistogram();
-}
-
-void ImageWindow::runQueue()
-{
-  bool swap_zoom = 0;
-
-  operations_string = "(";
-
-  if (process_queue != NULL)
-    {
-      for (int i=1; i<=process_queue->size(); i++)
-        {
-         Image_Operation *op = (Image_Operation *) process_queue->data(i);
-
-         assert(op);
-
-         if(!op->enabled)
-           continue;
-
-         if (i!=1)
-           operations_string += ";" ;
-         operations_string += op->name;
-         
-         for (int n=0; n<op->num_parameters; n++)
-           {
-             operations_string += "-";
-             ostringstream os;
-             os << op->parameters[n].value;
-             operations_string += os.str();
-           }
-
-          if (op->name == "sub fitplane") 
-            id.fitplane(op->parameters[0].value, op->parameters[1].value, op->parameters[3].value);
-          else if (op->name == "shift data") 
-            id.shift_data(op->parameters[0].value, op->parameters[1].value);
-          else if (op->name == "remove lines") 
-            id.remove_lines(op->parameters[0].value, op->parameters[1].value);
-         else if (op->name == "sub linecut")
-           id.sub_linecut(op->parameters[1].value, op->parameters[0].value);
-         else if (op->name == "outlier")
-           id.outlier_line(op->parameters[1].value, op->parameters[0].value);
-         else if (op->name == "scale axes")
-           id.scale_axes(op->parameters[0].value, op->parameters[1].value);
-         else if (op->name == "offset axes")
-           id.offset_axes(op->parameters[0].value, op->parameters[1].value);
-          else if (op->name == "sub plane") 
-            id.plane(op->parameters[0].value, op->parameters[1].value);
-          else if (op->name == "sub lbl") 
-            id.lbl(op->parameters[0].value, op->parameters[1].value, 0, 1, op->parameters[2].value, op->parameters[3].value);
-          else if (op->name == "sub cbc")
-            id.cbc(op->parameters[0].value, op->parameters[1].value, 0, 1, op->parameters[2].value, op->parameters[3].value);
-         else if (op->name == "power")
-           id.gamma(op->parameters[0].value,op->parameters[1].value);
-         else if (op->name == "scale data")
-           id.scale(op->parameters[0].value);
-         else if (op->name == "even odd")
-           id.even_odd(op->parameters[0].value, op->parameters[1].value);
-         else if (op->name == "rm switch")
-           id.switch_finder(op->parameters[0].value, op->parameters[1].value, false);
-         else if (op->name == "offset")
-           id.offset(op->parameters[0].value, op->parameters[1].value);
-          else if (op->name == "norm lbl") 
-            id.norm_lbl();
-          //else if (op->name == "square") 
-         //id.square();
-          else if (op->name == "norm cbc") 
-            id.norm_cbc();
-          else if (op->name == "log") 
-            id.log10(op->parameters[0].value, op->parameters[1].value);
-          else if (op->name == "interp") 
-            id.interpolate(op->parameters[0].value, op->parameters[1].value);
-          else if (op->name == "scale img") 
-            id.scale_image(op->parameters[0].value, op->parameters[1].value);
-          else if (op->name == "abs") 
-            id.magnitude();
-          else if (op->name == "neg") 
-            id.neg();
-         else if (op->name == "hist2d")
-           id.hist2d(op->parameters[0].value, op->parameters[1].value, op->parameters[2].value);
-          else if (op->name == "xderiv")
-            id.xderv();
-          else if (op->name == "yderiv")
-            id.yderv();
-          else if (op->name == "ederiv")
-           id.ederv(op->parameters[0].value,op->parameters[1].value);
-         else if (op->name == "dderiv")
-           id.dderv(op->parameters[0].value);
-         else if (op->name == "gradmag")
-           id.grad_mag(op->parameters[0].value);
-         else if (op->name == "lowpass")
-           id.lowpass(op->parameters[0].value, op->parameters[1].value,(ImageData::lowpass_kernel_t)op->parameters[2].value);
-         else if (op->name == "highpass")
-           id.highpass(op->parameters[0].value, op->parameters[1].value, op->parameters[2].value / 100.0, (ImageData::lowpass_kernel_t)op->parameters[3].value);
-         else if (op->name == "notch")
-           id.notch(op->parameters[0].value, op->parameters[1].value, op->parameters[2].value, op->parameters[3].value);
-         else if (op->name == "crop")
-           id.crop(op->parameters[0].value, op->parameters[1].value, op->parameters[3].value, op->parameters[2].value);
-         else if(op->name == "despeckle")
-           id.despeckle(op->parameters[0].value, op->parameters[1].value);
-         else if(op->name == "flip")
-           {
-             if(op->parameters[0].value)
-               id.xflip();
-             if(op->parameters[1].value)
-               id.yflip();
-           }
-         else if (op->name == "autoflip")
-           {
-             if (id.xmin > id.xmax)
-               id.xflip();
-             if (id.ymin > id.ymax)
-               id.yflip();
-           }
-         else if (op->name == "pixel avg")
-           id.pixel_average(op->parameters[0].value, op->parameters[1].value);   
-         else if(op->name == "rotate cw")
-           {
-             id.rotate_cw();
-             swap_zoom = !swap_zoom;
-           }
-         else if(op->name == "rotate ccw")
-           {
-             id.rotate_ccw();
-             swap_zoom = !swap_zoom;
-           }
-          else if (op->name == "equalize") 
-            id.equalize();
-         else
-           warn("Warning: unknown operation \"%s\"\n",process_queue->text(i));
-        }
-    }
-  
-  //info( "op string %s\n", operations_string.c_str());
-  operations_string += ")";
-  if (process_queue->size() == 0)
-    operations_string = "";
-
-  //info( "op string2 %s\n", operations_string.c_str());
-  //warn( "swap_zoom %d zoom_is_swapped %d\n", swap_zoom, zoom_is_swapped);
-
-  //info("op string2 %s\n", operations_string.c_str());
-  //info("zname %s\n", id.zname.c_str());
-
-  // We used to do id.zname = id.zname + operation_string, but this
-  // didn't work for the MTX data derived from meta.txt files? I
-  // coudn't figure it out, so we'll just use old-fashioned c
-  // functions...
-  char tmp[4096];
-  snprintf(tmp, sizeof(tmp), "%s %s", id.zname.c_str(), operations_string.c_str());
-  //  info("sum test: %s\n", tmp);
-  id.zname = tmp;
-  //info( "zname %s\n", id.zname.c_str());
-
-  if (swap_zoom != swap_zoom_state)
-    {
-      int tmp = xzoom;
-      xzoom = yzoom;
-      yzoom = tmp;
-    }
-  swap_zoom_state = swap_zoom;
-
-  // We also need to recalculate the peaks. If they're not displayed, it's no
-  // biggy, since it doesn't take too much time.
-  
-  // For some reason, this is reproducibly generating a segfault on
-  // win32?  with some specific input files (actually, in particular,
-  // a really big input file of 600x3600)
-
-  // However, I think the problem is deeper than this, since we were also
-  // getting random segfaults in win32 before peakfinder. 
-
-  // Running in gdb, it is segfaulting when calling iw->dataval
-
-  // Actually, I just realized that pf calls iw->dataval, which is no
-  // good since if this function is called from loadData, we may not
-  // have updated the iw width and height properly yet.
-
-  pf->calculate();
-}
-
-// a little procedure
-void ImageWindow::adjust_window_size()
-{
-  if (window_size_action == KEEPSIZE)
-    {
-      xzoom = 0; yzoom = 0;
-      size(((Fl_Widget *) this)->w(), ((Fl_Widget *)this)->h());
-    }
-  else if (window_size_action == KEEPZOOM)
-    setXZoom(xzoom); // call this to allocate the image array and set the window size.
-  else // if (window_size_action == RESETZOOM)
-    {
-      xzoom = 1; yzoom = 1;
-      setXZoom(xzoom);
-    }
-}
-
-int ImageWindow::loadData(const char *name) 
-{
-  // This is now completely rewritten!
-  filename = name;
-  if (id.load_file(name) == -1) return -1;
-  if (id.width == 0 || id.height == 0) return -1;
-  if ((id.width>id.height) && (id.width%id.height == 0) && square) 
-    id.pixel_average(id.width/id.height, 1);
-  original_dataname = id.zname;
-  runQueue();
-  id.quantize();
-  data = id.quant_data;
-
-  w = id.width;
-  h = id.height;
-
-  zap(databuf);
-  databuf = new int [w*h];
-
-  adjust_window_size();
-
-  calculateHistogram();
-  adjustHistogram();
-  plotLineCut();
-  plotHist();
-  
-  // Set a nice basename
-  char *p;
-  strncpy(output_basename, filename.c_str(), 256);
-  if ((p = strstr(output_basename, ".pgm")) == 0)
-    if ((p = strstr(output_basename, ".Stm")) == 0)
-      if ((p = strstr(output_basename, ".mtx")) == 0)
-       if ((p = strstr(output_basename, ".dat")) == 0)
-         p = strchr(output_basename, 0);
-  *p = 0;
-  
-  external_update();
-  return 0;
-}
-
-void ImageWindow::loadData(int *newdata, int neww, int newh, const char *name, bool reset_units)
-{
-  filename = "imagedata";
-  // Keep these around: if the image doesn't change size, we won't bother reallocating the arrays.
-  int oldw = w;
-  int oldh = h;
-
-  w = neww;
-  h = newh;
-
-  id.load_int(newdata, neww, newh);
-  if ((id.width>id.height) && (id.width%id.height == 0) && square) 
-    id.pixel_average(w/h, 1);
-  runQueue();
-  id.quantize();
-  data = id.quant_data;
-
-  w = neww = id.width;
-  h = newh = id.height;
-
-  if ( oldw*oldh != neww*newh )
-    {
-      zap(databuf);
-      databuf = new int [w*h];
-    }
-
-  adjust_window_size();
-
-  calculateHistogram();
-  adjustHistogram();
-  plotLineCut();
-  plotHist();
-  sprintf(output_basename, name);
-  external_update();
-}
-
-void ImageWindow::reRunQueue()
-{
-  int oldw = w;
-  int oldh = h;
-
-  // This will copy the original data back into the raw data matrix
-  id.reset();
-  if ((id.width>id.height) && (id.width%id.height == 0) && square) 
-    id.pixel_average(id.width/id.height, 1);
-  runQueue();
-  id.quantize();
-  data = id.quant_data;
-  
-  w = id.width;
-  h = id.height;
-
-  // since we will likely often be loading a dataset of the same dimesions
-  if ( oldw*oldh != w*h )
-    {
-      zap(databuf);
-      databuf = new int [w*h];
-    }
-
-  setXZoom(xzoom); // this will allocate the image array
-
-  calculateHistogram();
-  adjustHistogram();
-  plotLineCut();
-  plotHist();
-}
-
-void ImageWindow::load_mtx_cut(int index, mtxcut_t type)
-{
-  int oldw = w;
-  int oldh = h;
-
-  type = type %3;
-  
-  if (!id.data3d)
-    {
-      info( "3D data not loaded!\n");
-      return;
-    }
-  
-  id.load_mtx_cut(index, type);
-  original_dataname = id.zname;
-  runQueue();
-  id.quantize();
-  data = id.quant_data;
-  
-  w = id.width;
-  h = id.height;
-
-  // since we will likely often be loading a dataset of the same dimesions
-  if ( oldw*oldh != w*h )
-    {
-      zap(databuf);
-      databuf = new int [w*h];
-    }
-
-  setXZoom(xzoom); // this will allocate the image array
-
-  calculateHistogram();
-  adjustHistogram();
-  plotLineCut();
-  plotHist();
-  external_update();
-}
-
-
-void ImageWindow::saveFile() 
-{
-  char buf[256];
-  snprintf(buf, 256, "%s.ppm", output_basename);
-  FILE *fp = fopen(buf, "wb");
-  if(fp == NULL)
-    {
-      warn("Unable to open file \"%s\": %s\n",
-          buf, strerror(errno));
-      return;
-    }
-  fprintf(fp, 
-         "P6\n%d %d\n"
-         "#hmin %d %e %s\n"
-         "#hmax %d %e %s\n"
-         "#hwidth %d %e %s\n"
-         "#plane_a %e\n"
-         "#plane_b %e\n"
-         "#gamma %e\n"
-         "#Image processing: %s\n"
-         "255\n", w, h, 
-         hmin, id.quant_to_raw(hmin), id.zname.c_str(),
-         hmax, id.quant_to_raw(hmax), id.zname.c_str(),
-         hmax-hmin, id.quant_to_raw(hmax-hmin), id.zname.c_str(),
-         plane_a, plane_b, gam, operations_string.c_str());
-
-  unsigned char r,g,b;
-  for (int i = 0; i<w*h; i++)
-    {
-      makergb(data[i],r,g,b,i/w,i%w);
-      fwrite(&r, 1, 1, fp);
-      fwrite(&g, 1, 1, fp);
-      fwrite(&b, 1, 1, fp);
-    }
-       
-  fclose(fp);
-}
-
-void ImageWindow::fit_plane() //calculates plane_a, plane_b, and plane_c
-{
-  // Formula for the plane: Z = a*X + b*Y + c
-  double a,b,c;
-  // calculate the moments
-  int N = w*h;
-  double Zavg = 0;
-  double Xavg = 0;
-  double Yavg = 0;
-  double sXZ = 0;
-  double sYZ = 0;
-  double sXX = 0;
-  double sYY = 0;
-
-  for (int x=0; x < w; x++)
-    {
-      for (int y=0; y < h; y++)
-       {
-         Zavg += (double) data[y*w + x];
-         Xavg += (double) (x-w/2);
-         Yavg += (double) (y-h/2);
-         sXZ += (double) data[y*w + x] * (x-w/2);
-         sYZ += (double) data[y*w + x] * (y-h/2);
-         sXX += (double) (x-w/2)*(x-w/2);
-         sYY += (double) (y-h/2)*(y-h/2);
-       }
-    }
-
-  Xavg /= N;
-  Yavg /= N;
-  Zavg /= N;
-
-  a = (sXZ - N*Xavg*Zavg)/(sXX - N*Xavg*Xavg);
-  b = (sYZ - N*Yavg*Zavg)/(sYY - N*Yavg*Yavg);
-  c = Zavg - a*Xavg - b*Yavg - LMAX/2;
-  
-  //warn( "c = %f\n",c);
-  //warn( " a %10.2f\n b %10.2f\n c %10.2f\n", a, b, c);
-
-  plane_a = b;
-  plane_b = a;
-
-  plane_c = c;
-};
-
-int ImageWindow::planeval(int x,int y) 
-{
-  if (plane)
-    return (int) (plane_a * (x-w/2) + plane_b*(y-h/2));
-  else
-    return 0;
-}
-
-double Image_Operation::getParameter(const char *str)
-{
-  for(parameters_t::iterator i = parameters.begin(); i != parameters.end(); i++)
-    if(i->name == str)
-      return i->value;
-  warn("Warning: unknown parameter \"%s\" on image operation \"%s\"\n", str, name.c_str());
-  warn("Available parameters:\n");
-  for(parameters_t::iterator i = parameters.begin(); i != parameters.end(); i++)
-    warn("\t%s\n",i->name.c_str());
-  return 0.0;
-}
-
-void ImageWindow::dumpColormap()
-{
-  string fn = output_basename;
-  fn += ".colormap.dat";
-  info("dumping colormap to %s\n", fn.c_str());
-  FILE *fp = fopen(fn.c_str(), "w");
-  fprintf(fp, "# hmin %d hmax %d gamma %e\n", hmin, hmax, gam);
-  
-  unsigned char r,g,b;
-  int cmap_index;
-  for (int i=hmin; i<hmax; i++)
-    {
-      cmap_index = imagehist[i]*(colormap_length-1)/LMAX;
-      makergb(i, r, g, b);
-      fprintf(fp, "%d %d %e %d %d %d %d\n",
-             cmap_index, i, id.quant_to_raw(i), 
-             imagehist[i],  
-             r, g, b);
-    }
-  fclose(fp);
-}
-
-      
-
-void ImageWindow::exportLinecut()
-{
-  // Ok, this is a real hack, but it's easy...
-  char tmp[1024];
-  char label[1024];
-  char fn[1024];
-
-  //sprintf is just so damn more convenient than c++ strings
-  if (line_cut_type == HORZLINE) 
-    snprintf(label, 1024, "l.%d", line_cut_yp);
-  else if (line_cut_type == VERTLINE) 
-    snprintf(label, 1024, "c.%d", line_cut_xp);
-  else 
-    sprintf(label, "other");
-  snprintf(fn, 1024, "%s.%s.linecut.dat", output_basename, label);
-       
-  info("exporting linecut to file %s\n", fn);
-
-  strncpy(tmp, xsection_fn, 1024);
-  strncpy(xsection_fn, fn, 1024);
-  plotLineCut();
-  strncpy(xsection_fn, tmp, 1024);
-}
-
-void ImageWindow::exportGnuplot()
-{
-  FILE *fp;
-  //char buf1[256],buf2[256];
-  int i,j;
-  string base = output_basename;
-  // Output the data in pm3d format
-
-  //snprintf(buf1, 256, "%s.pm3d", output_basename);
-  if ((fp = fopenwarn((base+".gp").c_str(), "w")) == NULL)
-    return;
-
-  for (i=0; i<w; i++)
-    {
-      for (j=0; j<h; j++)
-       fprintf(fp, "%e %e %e\n", id.getX(i), id.getY(j), dataval(i,j));
-      fprintf(fp, "#\n\n");
-    }
-  fclose(fp);
-
-  // Now output a gnuplot script file to plot the data with the right colormap range.
-
-  //snprintf(buf2, 256, "%s.gnu", output_basename);
-  if ((fp = fopenwarn((base+".gnu").c_str(), "w")) == NULL)
-    return;
-  
-  fprintf(fp, "set palette defined (");
-  for (int i=0; i<colormap_length-1; i+=1)
-    fprintf(fp, "%f %f %f %f,", 1.0*i/(colormap_length-1), 1.0*colormap[3*i]/255.0, 1.0*colormap[3*i+1]/255.0, 1.0*colormap[3*i+2]/255.0);
-  fprintf(fp, "%f %f %f %f)\n", 1.0, 1.0*colormap[3*colormap_length-3]/255.0, 1.0*colormap[3*colormap_length-2]/255.0, 1.0*colormap[3*colormap_length-1]/255.0);
-
-  fprintf(fp, 
-         "set view map; set pm3d; set st d pm3d;\n"
-         "unset grid; set pm3d corners2color c1;\n"
-         "set cbrange [%e:%e];\n"
-         "set xrange [%e:%e]; set yrange [%e:%e]\n"
-         "set xlabel '%s'; set ylabel '%s'; set cblabel '%s'\n"
-         "splot \"%s\"\n", 
-         id.quant_to_raw(hmin), id.quant_to_raw(hmax),
-         id.getX(0), id.getX(w),
-         id.getY(h), id.getY(0),
-         id.xname.c_str(), id.yname.c_str(), id.zname.c_str(),
-         (base+".pm3d").c_str()); 
-  fclose(fp);
-
-}
-
-void ImageWindow::exportMAT()
-{
-  string name = output_basename;
-  name += ".export.dat";
-  FILE *fp;
-  if ((fp = fopenwarn(name.c_str(), "w")) == NULL)
-    return;
-  
-  for (int i=0; i<w; i++)
-    {
-      for (int j=0; j<h; j++)
-       fprintf(fp, "%e ", dataval(i,j));
-      fprintf(fp, "\n");
-    }
-  fclose(fp);
-}
-
-void ImageWindow::setupPS()
-{
-  imageprinter->updateSettings(&ipc);
-  if (ipc.win->shown())
-    ipc.win->hide();
-  else
-    ipc.win->show();
-}
-
-char *ImageWindow::exportPS()
-{  
-  //const char *extension = ipc.format->value() == Image_Printer::FORMAT_PDF ? "pdf" : "ps";
-  struct stat s;
-  FILE *fp;
-  static char buf[1024];  
-  static char buf2[1024];
-
-  if (ipc.auto_inc->value())
-    {
-      int number = 0;
-      snprintf(buf, sizeof(buf), "%s.%d", output_basename, number++);
-      while(stat(buf,&s) == 0) // Stat will return 0 if the file exists
-       {
-         snprintf(buf, sizeof(buf), "%s.%d", output_basename, number++);
-         if(number > 1000)
-           {
-             warn("Unable to come up with a suitable file name\n");
-             return NULL;
-           }
-       }
-      if(errno != ENOENT)
-       {
-         warn("Problem stating output file name: %s\n",strerror(errno));
-         return NULL;
-       }
-      ipc.incnum->value(number);
-    }
-  else if (ipc.do_number->value())
-    {
-      int n = ipc.incnum->value();
-      snprintf(buf, sizeof(buf), "%s.%d", output_basename, n);
-      if (ipc.increment->value())
-       ipc.incnum->value(n+1);
-    }
-  else
-    snprintf(buf, sizeof(buf), "%s", output_basename);
-
-  snprintf(buf2, sizeof(buf2), "%s.ps", buf);
-  info("outputting postscript file %s\n", buf2);
-  fp = fopen(buf2, "w");
-  imageprinter->print(fp);
-  fflush(fp);
-  fclose(fp);
-
-  // This will call ghostscript to do the extra conversions
-  imageprinter->do_extra_conversions(buf);
-  return buf2;
-}
-
-void ImageWindow::exportMTX(bool save, bool zoom)
-{
-  FILE *fp;
-
-  string name = output_basename;
-
-  if (save)
-    name += ".mtx";
-  else if (zoom)
-    name += ".zoom.mtx";
-  else
-    name += ".export.mtx"; 
-
-  info("save %d name %s\n", save, name.c_str());
-
-  if ((fp = fopen(name.c_str(), "r")) != NULL && (save || zoom))
-    {
-      if (fl_ask("Overwrite file %s", name.c_str()) == 1)
-       fclose(fp);
-      else
-       {
-         fclose(fp);
-         return;
-       }
-    }
-
-  if ((fp = fopenwarn(name.c_str(), "wb")) == NULL)
-    return;
-  
-  int x1, y1, x2, y2;
-  double xmin, ymin, xmax, ymax;
-
-  if (zoom)
-    {
-      zoom_window->getSourceArea(x1,y1,x2,y2);
-      x2--;
-      y2--;
-    }
-  else
-    {
-      x1 = 0; x2 = id.width-1;
-      y1 = 0; y2 = id.height-1;
-    }
-  
-  xmin = id.getX(x1);
-  xmax = id.getX(x2);
-  ymin = id.getY(y1);
-  ymax = id.getY(y2);
-
-  int wid = x2-x1+1;
-  int hgt = y2-y1+1;
-
-  string zname = search_replace(id.zname, ",", ";");
-  string xname = search_replace(id.xname, ",", ";");
-  string yname = search_replace(id.yname, ",", ";");
-  
-  fprintf(fp, "Units, %s,"
-         "%s, %e, %e,"
-         "%s, %e, %e," 
-         "Nothing, 0, 1\n",
-         zname.c_str(), 
-         xname.c_str(), xmin, xmax,
-         yname.c_str(), ymin, ymax);
-  fprintf(fp, "%d %d 1 8\n", wid, hgt);
-
-  //info("x1 %d x2 %d width %d\n", x1, x2, wid);
-  //info("y1 %d y2 %d height %d\n", y1, yq2, hgt);
-
-  for (int i=x1; i<=x2; i++)
-    for (int j=y1; j<=y2; j++)
-      fwrite(&id.raw(i,j), sizeof(double), 1, fp);
-  
-  fclose(fp);
-}
-
-void ImageWindow::exportPGM()
-{
-  FILE *fp;
-  char buf[256];
-  int i,j;
-
-  snprintf(buf, 256, "%s.export.pgm", output_basename);
-
-  if ((fp = fopenwarn(buf, "wb")) == NULL)
-    return;
-  
-  fprintf(fp, "P5\n%d %d\n", w, h);
-  fprintf(fp, "#zmin %e\n"
-         "#zmax %e\n"
-         "#xmin %e\n"
-         "#xmax %e\n"
-         "#ymin %e\n"
-         "#ymax %e\n"
-         "#xunit %s\n"
-         "#yunit %s\n"
-         "#zunig %s\n"
-         "#Image Processing: %s\n"
-         "65535\n", id.qmin, id.qmax, id.xmin, id.xmax, id.ymin, id.ymax,
-         id.xname.c_str(), id.yname.c_str(), id.zname.c_str(), 
-         operations_string.c_str());
-  
-  char c;
-  int val;
-  for (j=0; j<h; j++)
-    for (i=0; i<w; i++)
-      {
-       val = data[j*w+i]-planeval(j,i); 
-       c = val/256; 
-       fwrite(&c,1,1,fp);
-       c = val%256;
-       fwrite(&c,1,1,fp);
-      }
-  fclose(fp);
-}
-
-void ImageWindow::exportMatlab()
-{
-  FILE *fp;
-  char buf[256];
-
-  string base = output_basename;
-
-  // Matlab M-file names can contain only alphanumeric characters!
-  // http://authors.ck12.org/wiki/index.php/Introduction_to_Programming_with_M-file_Scripts
-  // How annoying...
-
-  for (int pos = 0; pos < base.size(); pos++)
-    if (!isalnum(base[pos]) && 
-       base[pos] != '\\' &&  // we should not replace directory separators...
-       base[pos] != ':' &&
-       base[pos] != '/')
-      base[pos] = '_';
-  
-  info("Outputting file %s\n", (base+".m").c_str());
-
-  if ((fp = fopenwarn((base+".m").c_str(), "w")) == NULL)
-    return;
-  
-  // Output the current colormap
-  fprintf(fp, "cmap = [ ");
-  for (int i=0; i<colormap_length; i+=1)
-    {
-      int tmp = gammatable[i];
-      fprintf(fp, "%f %f %f ", 
-             1.0*colormap[3*tmp]/255.0, 
-             1.0*colormap[3*tmp+1]/255.0, 
-             1.0*colormap[3*tmp+2]/255.0);
-      if (i != colormap_length-1)
-       fprintf(fp, ";\n");
-    }
-  fprintf(fp, "];\n");
-
-  fprintf(fp, "data = [ ");
-  for (int j=0; j<h; j++)
-    {
-      for (int i=0; i<w; i++)
-       fprintf(fp, "%e ", dataval(i,j));
-      if (j != h-1)
-       fprintf(fp, ";\n");
-    }
-  fprintf(fp, "];\n");
-
-  double min = id.quant_to_raw(hmin);
-  double max = id.quant_to_raw(hmax);
-  
-
-  fprintf(fp, 
-         "figure(1)\n"
-         "colormap(cmap)\n"
-         "imagesc(data)\n"
-         "caxis([%e %e])\n"
-         "figure(2)\n"
-         "colormap(cmap)\n"
-         "surf(data)\n"
-         "caxis([%e %e])\n"
-         "shading flat\n"
-         "lighting gouraud\n"
-         "camlight\n", 
-         min, max, min, max);
-  fclose(fp);
-}
-
-// Zoom window support
-
-void ZoomWindow::realloc_image()
-{
-  if((image == NULL) || (image_size != static_cast<size_t>(w()*h())))
-    {
-      if(image != NULL)
-       free(image);
-      image_size = w()*h();
-      image = (unsigned char *)malloc(sizeof(unsigned char) * image_size * 3);      
-    }
-}
-ZoomWindow::ZoomWindow(int w, int h, const char *title) : Fl_Double_Window(w,h,title), image(NULL), img(NULL), xscale(2),yscale(2), center_x(0), center_y(0)
-{
-  autonormalize = false;
-}
-
-void ZoomWindow::calculateHistogram()
-{
-  int x1,y1,x2,y2;
-  getSourceArea(x1,y1,x2,y2);
-  for(unsigned i = 0; i < hist_len; i++)
-    histogram[i] = 0;
-  for(int x = x1; x < x2; x++)
-    for(int y = y1; y < y2; y++)
-      {
-       int d = img->id.quant(x,y);
-       if(d >= 0 && d < static_cast<int>(hist_len))
-         histogram[d]++;   
-      }
-}
-
-void ZoomWindow::draw()
-{
-  if(!img)
-    return;
-  realloc_image();
-  int src_x1, src_y1, src_x2, src_y2;
-  getSourceArea(src_x1, src_y1, src_x2, src_y2);
-  int my = h();
-  int mx = w();
-  unsigned char *p = image;
-  for(int y = 0; y < my; y++)
-    for(int x = 0; x < mx; x++)
-      {
-       int sx = src_x1 + x/xscale;
-       int sy = src_y1 + y/yscale;
-       if(sx >= src_x2 || sy >= src_y2)
-         {
-           *p++=0;
-           *p++=0;
-           *p++=0;
-           continue;
-         }
-       else
-         {
-           unsigned char r,g,b;
-           img->getrgb(sy,sx,r,g,b);
-           *p++=r;
-           *p++=g;
-           *p++=b;
-         }     
-      }
-  fl_draw_image(image,0,0,mx,my,3,0);
-  // This is sometimes getting out of sync: put in the redraw...
-  snprintf(window_label, 256, "Zoom of %s: (%dx,%dx)", img->filename.c_str(), xscale, yscale);
-  label(window_label);
-}
-
-int ZoomWindow::handle(int event)
-{
-  switch (event)
-    {    
-    case FL_PUSH:
-      push_mouse_x = Fl::event_x();
-      push_mouse_y = Fl::event_y();
-      push_center_x = center_x;
-      push_center_y = center_y;
-      break;
-    case FL_DRAG:
-    case FL_RELEASE:
-      center_x = push_center_x - (Fl::event_x()-push_mouse_x)/xscale;
-      center_y = push_center_y - (Fl::event_y()-push_mouse_y)/yscale;
-      zoomMoved();
-      break;
-    case FL_HIDE:
-      if(img)
-       img->redraw_overlay();
-      break;
-    case FL_SHOW:
-      if(img)
-       img->redraw_overlay();
-      break;
-    case FL_KEYDOWN:
-      char c = Fl::event_key();
-      //info("Key %c\n",c);
-      switch(c)
-       {
-       case '=':
-       case '+':
-       case '.':
-       case '>':
-         {
-           int oldw, oldh;
-           oldw = w()/xscale;
-           oldh = h()/yscale;
-           if (Fl::event_state() & FL_SHIFT)
-             xscale++;
-           else if (Fl::event_state() & FL_CTRL)
-             yscale++;
-           else
-             {xscale++; yscale++;}
-           size(oldw*xscale, oldh*yscale);
-           if(img)
-             img->redraw_overlay();
-           redraw();
-           return 1;
-         }
-       case '-':
-       case ',':
-       case '<':
-         {
-           int oldw, oldh;
-           oldw = w()/xscale;
-           oldh = h()/yscale;
-           if (Fl::event_state() & FL_SHIFT)
-             xscale--;
-           else if (Fl::event_state() & FL_CTRL)
-             yscale--;
-           else
-             {xscale--; yscale--;}
-           if(xscale < 1)
-             xscale = 1;
-           if(yscale < 1)
-             yscale = 1;
-           size(oldw*xscale, oldh*yscale);
-           if(img)
-             img->redraw_overlay();
-           redraw();
-           return 1;
-         }
-       case 'z':
-         if (!(Fl::event_state() & FL_CTRL))
-           {
-             hide();
-             return 1;
-           }
-       }
-      break;
-    }
-  return 0;
-}
-
-void ZoomWindow::resize(int x, int y, int w, int h)
-{
-  snprintf(window_label, 256, "Zoom of %s: (%dx,%dx)", img->filename.c_str(), xscale, yscale);
-  label(window_label);
-  Fl_Double_Window::resize(x,y,w,h);
-  img->external_update();
-  zoomMoved();
-  size_range(1,1);
-} 
-
-void ZoomWindow::getSourceArea(int &x1, int &y1, int &x2, int &y2)
-{
-  int dx = w()/xscale;
-  int dy = h()/yscale;
-  
-  //warn( "xscale %d yscale %d\n", xscale, yscale);
-
-  x1 = center_x - dx/2; // Find the ideal top-left
-  y1 = center_y - dy/2;
-
-  if(x1 < 0) x1 = 0; // Clip to the window
-  if(y1 < 0) y1 = 0;
-
-  x2 = x1 + dx; // Find the bottom right, including top-left clipping
-  y2 = y1 + dy;
-
-  if(x2 >= img->w) // Clip the bottom right to the window
-    {
-      x2 = img->w;
-      if(x2-dx < 0) // Be careful if the source window isn't as wide as dx!
-       x1 = 0;
-      else
-       x1 = x2-dx;
-    }
-  if(y2 >= img->h)
-    {
-      y2 = img->h;
-      if(y2-dy < 0)
-       y1 = 0;
-      else
-       y1 = y2-dy;
-    }
-}
-
-void ZoomWindow::zoomMoved()
-{
-  if(autonormalize && img)
-    img->normalizeOnZoom();
-  redraw();
-  if(img)
-    img->redraw_overlay();
-}
-
-ColormapWindow::ColormapWindow(int wp, int hp, const char *title) : Fl_Window(wp,hp,title), image(NULL)
-{  
-  // You shouldn't call functions from a constructor!
-  //resize(x(),y(),w(),h());
-  //size_range(1,1,0,0);
-}
-
-void ColormapWindow::resize(int x, int y, int w, int h)
-{
-  Fl_Window::resize(x,y,w,h);
-
-  if(image)
-    delete[] image;
-  image = NULL; 
-
-  if(h < w)
-    {
-      vertical = false;
-      xmult = w/wid;
-      //warn( "xmult %d\n", xmult);
-      if(xmult == 0)
-       return;
-      ih = h;
-      iw = w - (w % wid);
-    }
-  else
-    {
-      vertical = true;
-      xmult = h/wid;
-      //warn( "xmult %d\n", xmult);
-      if(xmult == 0)
-       return;
-      ih = w;
-      iw = h - (h % wid);
-    }
-  if(iw <= 0 || ih <= 0)
-    return;
-  image = new uchar[3*iw*ih];
-  assert(image);  
-  update();
-  redraw();
-}
-
-ColormapWindow::~ColormapWindow()
-{
-  delete[] image;
-}
-
-void ColormapWindow::update()
-{
-  if(!img || !image)
-    return;
-
-  double foo = 1.0 * (img->colormap_length-1)/(iw-1);
-  int tmp, tmp2;
-  int i;
-  for (int y = 0; y < ih; y++)
-    for (int x = 0; x < iw; x++)
-      {
-       tmp2 = (int) round(x*foo);
-       tmp = img->gammatable[tmp2];
-       if (vertical)
-         i = iw-1-x;
-       else
-         i = x;
-       
-//     if (x == iw/2 && y == 0)
-//       {
-//         warn( "iw %d cmapl %d foo %g x %d tmp2 %d tmp %d\n", 
-//                 iw, img->colormap_length, foo, x, tmp2, tmp);
-//       }
-       if(tmp > img->colormap_length-1)
-         tmp = img->colormap_length-1;
-       if(tmp < 0)
-         tmp = 0;
-       image[3*(i+y*iw)] = img->colormap[3*tmp];
-       image[3*(i+y*iw)+1] = img->colormap[3*tmp+1];
-       image[3*(i+y*iw)+2] = img->colormap[3*tmp+2];   
-      }
-  redraw();
-}
-void ColormapWindow::draw()
-{
-  if(image)
-    if(vertical)
-      fl_draw_image(image,0,(h()-iw)/2,ih,iw,iw*3,3);      
-    else
-      fl_draw_image(image,(w()-iw)/2,0,iw,ih,3,0);      
-}
-
-void ColormapWindow::saveFile(const char *name)
-{
-  static const int height=32;
-  warn( "saving colormap to %s", name);
-  FILE *fp = fopen(name, "wb");
-  if(fp == NULL)
-    {
-      warn("Unable to open file \"%s\": %s\n",
-          name, strerror(errno));
-      return;
-    }
-  fprintf(fp, 
-         "P6\n%d %d\n"
-         "#zmin %f\n"
-         "#zmax %f\n"
-         "255\n", wid, height, 
-         img->zunit(img->hmin),
-         img->zunit(img->hmax));
-
-  for(int j = 0; j < height; j++)
-    for (int i = 0; i< wid; i++)
-      {
-       int tmp = img->gammatable[i];
-       fwrite(&(img->colormap[3*tmp]),sizeof(char),3,fp);
-      }
-       
-  fclose(fp);
-}
-
diff --git a/spyview/bisector.H.~1.3.~ b/spyview/bisector.H.~1.3.~
deleted file mode 100644 (file)
index 9b696ef..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-#ifndef __bisector_h__
-#define __bisector_h__
-#include <assert.h>
-#include <math.h>
-
-class bisector
-{
-public:
-  static const double factor=0.5;
-  double x1, x2, fx1, fx2;
-  double acc;
-  int iter;
-  bisector(double x1p, double fx1p, double x2p, double fx2p, double acct=1e-6) : x1(x1p), x2(x2p), fx1(fx1p), fx2(fx2p), acc(acct*fabs(x1p-x2p))
-  {
-    iter =0;
-  };
-
-  bool x(double &xp) // Return next x coordinate to evaluate.  Return true if we've converged.
-  {
-    if(fx1*fx2 > 0)
-      {
-       if(fabs(fx1) < fabs(fx2))
-         {
-           xp = x1;
-           return true;
-         }
-       else
-         {
-           xp = x2;
-           return true;
-         }
-      }
-    if(fabs(x2-x1) < acc)
-      {
-       xp = (x1+x2)/2.0;
-       return true;
-      }
-    if(iter++ > 100)
-      {
-       fprintf(stderr,"x1=%g, x2=%g, acc=%g; bailing\n",
-               x1,x2,acc);
-       xp=(x1+x2)/2.0;
-       return true;
-      }
-    xp = x1+factor*(x2-x1);
-    return false;
-  };
-
-  inline void o(double x, double fx) // Add an observation.
-  {
-    if(fx*fx1 <= 0.0)
-      {
-       x2 = x;
-       fx2 = fx;
-      }
-    else
-      {
-       assert(fx*fx2 <= 0.0);
-       x1 = x;
-       fx1 = fx;
-      }
-  };
-};
-
-/* Newton step until we bracket, then bisect */
-class magic_bisector
-{
-public:
-  static const double factor=0.5;
-  bool bisection;
-  double nx, nfx;
-  double x1, fx1, x2, fx2, mest;
-  double acc;
-  int iter;
-  magic_bisector(double x_start, double m_est_p, double acc_p=1e-6) : nx(x_start), mest(m_est_p), acc(acc_p) 
-  { 
-    x1 = NAN;
-    x2 = NAN;
-    nfx = 10*acc_p; 
-    bisection = false;
-    iter = 0;
-  };
-  bool x(double &xp)
-  {
-    xp = nx;    
-    return (fabs(nfx) < acc) || (iter++ > 32);
-  }
-
-  void o(double xp, double fxp)
-  {
-    nfx = fxp;
-    if(bisection)
-      {
-       if(fxp < 0)
-         {
-           x1 = xp;
-           fx1 = fxp;
-         }
-       else
-         {
-           x2 = xp;
-           fx2 = fxp;
-         }
-      }
-    else
-      {
-       if(fxp < 0 && (isnan(x1) || (fxp > fx1)))
-         {
-           x1 = xp;
-           fx1 = fxp;
-         }
-       else if(fxp > 0 && (isnan(x2) || (fxp < fx2)))
-         {
-           x2 = xp;
-           fx2 = fxp;
-         }
-      }
-    bisection = !(isnan(x1) || isnan(x2));
-    if(bisection)
-      {
-       //      printf("Bisection step: [%g,%g] {%g,%g}\n", x1,x2,fx1,fx2);
-       nx = (x1+x2)/2.0;
-      }
-    else
-      {
-       nx -= nfx/mest;
-       //      printf("Newton step to %g (%g/%g)\n",nx,nfx,mest);
-      }
-  }
-};
-#endif
diff --git a/spyview/spypal_import.C.~1.6.~ b/spyview/spypal_import.C.~1.6.~
deleted file mode 100644 (file)
index e1b75f1..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-#include "spypal_import.H"
-#include <stdio.h>
-#include <math.h>
-
-double sqr(double x) { return x*x; };
-static int worst_point;
-static double worst_error;
-double spypal_worst_error() { return worst_error; };
-static double fidelity(unsigned char *c1, unsigned char *c2, unsigned l)
-{
-  double e = 0;
-  worst_error = 0; 
-  worst_point = -1;
-  for(unsigned i = 0; i < l; i++)
-    {
-      double se = sqr(c2[3*i]-c1[3*i])+sqr(c2[3*i+1]-c1[3*i+1])+sqr(c2[3*i+2]-c1[3*i+2]);
-      if(se > worst_error)
-       {
-         worst_point = i;
-         worst_error = se;
-       }
-      e += se;
-    }
-  return e;
-}
-
-static void color_waypoints(std::vector<SpypalWaypoint> &wps, unsigned char *c1, unsigned l)
-{
-  for(unsigned i = 0 ; i < wps.size(); i++)
-    {
-      double r,g,b;
-      r = c1[3*wps[i].ind+0]/255.0;
-      g = c1[3*wps[i].ind+1]/255.0;
-      b = c1[3*wps[i].ind+2]/255.0;
-      //      printf("%d %g %g %g %d %d %d\n",wps[i].ind,r,g,b,c1[3*wps[i].ind+0],c1[3*wps[i].ind+1],c1[3*wps[i].ind+2]);
-      cc_sRGB.set(wps[i].c,r,g,b);
-    }
-}
-static double try_colormap(std::vector<SpypalWaypoint> &wps, const ccspace *cs, unsigned  char *c1, unsigned l)
-{
-  sort(wps.begin(),wps.end());
-
-  generate_go(wps,OPTS_STRAIGHT,true,cs,cs,l);
-  if(cmap.size() != l)
-    return NAN;
-  dump_colormap_memory();
-  return fidelity(c1,spypal_colormap,l);
-}
-
-// Try to adjust the waypoints by starting from three waypoints, then building
-// up, adding the additional waypoint at the point where the error is largest
-// each time.
-double spypal_bisect_anneal(SpypalWaypoints_t &wps_out, const ccspace *cs, unsigned char *c1, unsigned l)
-{
-  size_t size = wps_out.size();
-  assert(size >= 2);
-
-  if(size == 2)
-    return spypal_anneal(wps_out,cs,c1,l);
-
-  double err;
-  SpypalWaypoints_t wps(3);
-
-  // Initialize the guess.
-  for(unsigned i = 0; i < wps.size(); i++)
-    {
-      wps[i].loc = ((double)i)/(wps.size()-1);
-      wps[i].ind = wps[i].loc * (l-1);
-      wps[i].locked = true;
-    }
-  color_waypoints(wps,c1,l);
-  err = spypal_anneal(wps,cs,c1,l,false);
-
-  // Add a waypoint at the worst point and anneal until we reach the right size
-  while(wps.size() < size)
-    {
-      SpypalWaypoint w;
-      if(worst_point >= 0)
-       w.ind = worst_point;
-      else
-       w.ind = l/2;
-      w.loc = ((double)w.ind) / (l-1);
-      w.locked = true;
-      wps.push_back(w);
-      color_waypoints(wps,c1,l);
-      err = spypal_anneal(wps,cs,c1,l,false);
-    }
-  wps_out = wps;
-  return try_colormap(wps,cs,c1,l);
-}
-
-// Try to adjust the waypoints in waypoints to maximize the fidelity.
-// Return the fidelity.
-double spypal_anneal(SpypalWaypoints_t &wps, const ccspace *cs, unsigned char *c1, unsigned l, bool init)
-{
-  double best;
-  SpypalWaypoints_t wps_best;
-
-  if(init)
-    {
-      // Initialize the guess.
-      for(unsigned i = 0; i < wps.size(); i++)
-       {
-         wps[i].loc = ((double)i)/(wps.size()-1);
-         wps[i].ind = wps[i].loc * (l-1);
-         wps[i].locked = true;
-       }
-      color_waypoints(wps,c1,l);
-    }
-
-  // Get an initial fidelity
-  best = try_colormap(wps,cs,c1,l);
-  if(isnan(best))
-    return best;
-  wps_best = wps;
-
-  // Anneal; try sliding each waypoint left then right.
-  bool improved;
-  int iter = 1000;
-  int stepsize = l/(2.0*wps.size());
-  if(stepsize < 1)
-    stepsize = 1;
-  do
-    {   
-      improved = false;
-      for(unsigned i = 1; i < wps.size()-1; i++)
-       {
-         if(wps[i].ind > stepsize)
-           {
-             SpypalWaypoints_t wpst = wps;
-             wpst[i].ind -= stepsize;
-             wpst[i].loc = wpst[i].ind / (l - 1.0);
-             color_waypoints(wpst,c1,l);
-             double f = try_colormap(wpst,cs,c1,l);
-             if(f < best)
-               {
-                 best = f;
-                 wps_best = wpst;
-                 improved = true;
-                 wps = wpst;
-                 break;
-               }
-           }
-         if(((int)wps[i].ind) < (l-stepsize))
-           {
-             SpypalWaypoints_t wpst = wps;
-             wpst[i].ind += stepsize;
-             wpst[i].loc = wpst[i].ind / (l - 1.0);
-             color_waypoints(wpst,c1,l);
-             double f = try_colormap(wpst,cs,c1,l);
-             if(f < best)
-               {
-                 best = f;
-                 wps_best = wpst;
-                 improved = true;
-                 wps = wpst;
-                 break;
-               }
-           }
-       }      
-      if(best == 0.0)
-       break;
-      if(!improved)
-       {
-         if(stepsize == 1)
-           break;
-         else
-           stepsize /= 2.0;
-       }
-      //      printf("%5d %3d %g\n",iter,stepsize,best);
-    }
-  while(iter--);
-  wps = wps_best;
-  // One extra calc cycle to get worst_error right.
-  return best; 
-}
diff --git a/spyview/spyview.C.~1.272.~ b/spyview/spyview.C.~1.272.~
deleted file mode 100644 (file)
index 8daac38..0000000
+++ /dev/null
@@ -1,2156 +0,0 @@
-#include <assert.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include "../config.h"
-#include <FLTK_Serialization.H>
-#include "spyview.H"
-#include "ImageWindow.H"
-#include "spyview_ui.h"
-#include "ImageWindow_LineDraw.H"
-#include "ImageWindow_Fitting.H"
-#include "ThresholdDisplay.H"
-#include "message.h"
-#include <Fl/fl_ask.H>
-#include <string.h>
-#include <Fl/Fl_File_Chooser.H>
-#include <Fl/filename.H>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <map>
-#include "Fiddle.H"
-#include "mypam.h"
-#include "misc.h"
-#include "spypal.h"
-#include "spypal_interface.H"
-#include "spypal_import.H"
-#include <libgen.h>
-
-using namespace std;
-
-//How's this for lazy...?
-char **arg_values;
-int arg_count;
-int opt_index;
-
-vector<string> filenames;
-vector<string> cmapfiles;
-string default_file;
-string current_filename;
-
-
-bool no_files_given;
-
-// Keep track of what directory we started in
-string original_dir("");
-
-// On unix, this will be $HOME/.spyview
-// On win32, default will be $APPDATA/spyview
-// If SPYVIEW_PREF_DIR exist, it will use $SPYVIEW_PREF_DIR/spyview
-string userdir("");
-
-// On unix, default to /usr/share
-// On windows, if called using file associations, we can find the full
-// path to the spyview.exe. If called from the command line, the user
-// should set the SPYVIEW_DIR environment variable.
-string sharedir("");
-
-int check_loaded()
-{
-  return filenames.size();
-}
-
-void clear_files()
-{
-  filech->clear();
-  filenames.clear();
-}
-
-void spyview_exit()
-{
-  // Will the iw destructor get called automatically on hide?
-  // However, it is important not to delete it before hiding all of
-  // the windows, as if the zoom window is open, then it will crash on
-  // win32 when it tries to call the draw_overlay() of iw after it's
-  // been deleted.
-
-  //delete iw; 
-
-  // Just calling exit(0) will rely on the OS to clear all of the
-  // memory. While this seems to work fine on UNIX, on win32, this
-  // results in intermittent and unpredictable crashes. According to
-  // this reference, http://www3.telus.net/public/robark/, it is
-  // better to hide all of the windows, which will call Fl::run() to
-  // return more safely (?)
-
-  while( Fl::first_window() )
-    Fl::first_window()->hide();  
-}
-
-void close_window_callback(Fl_Widget*)
-{
-  //if (fl_ask("Juriaan, do you really want to close spyview?")) // Who is Juriaan?
-  spyview_exit();
-
-  // I had never clicked on the "close" button of the image window
-  // before, and so I had never noticed the bug that if you close the
-  // ImageWindow, the program doesn't close, but then it is impossible
-  // to get the window to appear again.
-
-  // This bug was found by one of my earlier Windows-based spyview
-  // adopters, Juriaan. My initial answer was "why would you ever
-  // click on the close button of the window?", but I eventually caved
-  // and added this exit handler, and the warning message...
-
-}
-
-// Find all the colormaps in a path, using "pretty_path" for the browser
-// hierarchy.
-void find_cmaps(std::string path, std::string pretty_path)
-{
-  typedef vector<string> subdirs_t;
-  subdirs_t subdirs;
-  info("Checking \"%s\" for cmaps (%s)\n", path.c_str(),pretty_path.c_str());
-  struct dirent **namelist;
-  string fn;
-  int n = fl_filename_list(path.c_str(), &namelist, fl_casealphasort);
-  int count = 0;
-  for (int i = 0; i<n ; i++)
-    {
-      if ((strstr(namelist[i]->d_name, ".ppm") != NULL) || (strstr(namelist[i]->d_name,".spp") != NULL))
-       {
-         fn = namelist[i]->d_name;
-         std::string pretty_fn(fn);
-         pretty_fn.erase(pretty_fn.find_last_of('.'));
-         cmapfiles.push_back(path + fn);
-         int ind = cmapch->add((pretty_path + pretty_fn).c_str(), 0, 0, reinterpret_cast<void *>(cmapfiles.size()-1));
-         if(strstr(namelist[i]->d_name,".ppm") != NULL)
-           cmapch->menu()[ind].labelfont(FL_HELVETICA_ITALIC);
-         else
-           cmapch->menu()[ind].labelfont(FL_HELVETICA);
-         count++;        
-       }
-      else if (fl_filename_isdir((path+namelist[i]->d_name).c_str()))
-       subdirs.push_back(namelist[i]->d_name);
-      if ((count != 0) && (count%30 == 0))
-       pretty_path += "More/";
-   }
-  for(subdirs_t::iterator i = subdirs.begin(); i != subdirs.end(); i++)
-    {
-      if(*i == "./" || *i == "../" || *i == "")
-       continue;
-      find_cmaps(path+*i,pretty_path+*i);
-    }
-}
-
-int add_file(const char *name)
-{
-  // We store the actual filenames in a STL vector of strings
-  // called "filenames" 
-  
-  // In "filech", we put a "user friendly" filename in, and we
-  // store the index location of the real filename in the
-  // userdata.
-  
-  string menu_text;
-  int fd;
-  int n;
-  if ( (fd = open(name, O_RDONLY)) != -1)
-    {
-      filenames.push_back(name);
-      n=filech->add("foo", 0, filech_cb, reinterpret_cast<void *>(filenames.size()-1));
-      filech->replace(n, name);
-      close(fd);
-      return n;
-    }
-  else
-    {
-      warn("Unable to open file \"%s\": %s\n", name, strerror(errno));
-      return -1;
-    }
-}
-
-
-// breaks apart a string into substrings separated by a character string
-// does not use a strtok() style list of separator characters
-// returns a vector of std::strings
-
-std::vector<std::string> Explode (const std::string &inString, const std::string &separator)
-{ 
-  std::vector<std::string> returnVector;
-  std::string::size_type start = 0;
-  std::string::size_type end = 0;
-  
-  while ((end = inString.find (separator, start)) != std::string::npos)
-    {
-      returnVector.push_back (inString.substr (start, end-start));
-      start = end + separator.size();
-    }
-  
-  returnVector.push_back(inString.substr(start, inString.size()));
-  return returnVector;
-}
-
-// A drag-n-drop handler
-void load_filech(const char *text)
-{
-  info("test is:\n_%s_", text);
-  vector <string> files = Explode(text, "\n");
-  info("found %d files\n", files.size());
-
-  int n;
-  for (unsigned i=0; i<files.size(); i++)
-    {
-      info("adding file '%s'\n", files[i].c_str());
-      n=add_file(files[i].c_str());
-      if (n == -1)
-       return;
-    }
-  filech->value(n);
-  filech->do_callback();
-}
-
-int load_orig_files()
-{
-  filenames.clear();
-  filech->clear();
-  for (int i=opt_index; i < arg_count; i++)
-    add_file(arg_values[i]);
-  no_files_given = false;
-  if (filenames.size() == 0)
-    {
-      no_files_given = true;
-      add_file(default_file.c_str());
-      if (check_loaded() == 0)
-       error("Could not find default image!");
-    }
-  return 0;
-}
-
-/* Callbacks for image operations */
-// Callbacks for crop
-void cb_crop_to_zoom(Fl_Widget *w, void *p)
-{
-  int x1,y1,x2,y2;
-  if(!iw->zoom_window)
-    return;
-  iw->zoom_window->getSourceArea(x1,y1,x2,y2);
-  char buf[1024];
-  snprintf(buf,sizeof(buf),"%d",x1);
-  proc_parameters[0]->value(buf);
-  snprintf(buf,sizeof(buf),"%d",x2);
-  proc_parameters[1]->value(buf);
-  snprintf(buf,sizeof(buf),"%d",y1);
-  proc_parameters[2]->value(buf);
-  snprintf(buf,sizeof(buf),"%d",y2);
-  proc_parameters[3]->value(buf);
-  proc_parameters[3]->do_callback();
-}
-
-void cb_reset_zoom(Fl_Widget *w, void *p)
-{
-  proc_parameters[0]->value("0");
-  proc_parameters[1]->value("0");
-  proc_parameters[2]->value("0");
-  proc_parameters[3]->value("0");
-  proc_parameters[3]->do_callback();
-}
-
-// Callbacks for line subtraction
-void cb_sub_current_line(Fl_Widget *w, void *p)
-{
-  int line;
-  if(proc_bool_parameters[1]->value())
-    line = iw->line_cut_yp;
-  else
-    line = iw->line_cut_xp;
-  char buf[1024];
-  snprintf(buf,sizeof(buf),"%d",line);
-  proc_parameters[0]->value(buf);
-  proc_parameters[0]->do_callback();  
-}
-
-void cb_hist2d_autorange(Fl_Widget *w, void *p)
-{
-  double tmp;
-  char buf[1024];
-
-  tmp = iw->id.quant_to_raw(iw->hmin);
-  snprintf(buf,sizeof(buf),"%e",tmp);
-  proc_parameters[0]->value(buf);
-
-  tmp = iw->id.quant_to_raw(iw->hmax);
-  snprintf(buf,sizeof(buf),"%e",tmp);
-  proc_parameters[1]->value(buf);
-
-  snprintf(buf,sizeof(buf),"%d",iw->id.height);
-  proc_parameters[2]->value(buf);
-
-  proc_parameters[0]->do_callback();
-}
-
-void usage()
-{
-  printf("%s\n",Fl::help);
-}
-
-
-void Update_Status_Bar(int n, bool down);
-void embed_colormap();
-void showUsedFiles(bool leak); // For debugging
-int main(int argc, char **argv)
-{
-  char c;
-  Fl::visual(FL_RGB8|FL_DOUBLE);
-  Fl::get_system_colors();
-  info("Welcome to spyview\n");
-  info("Build stamp: %s\n", BUILDSTAMP);
-
-  char buf[1024];
-  original_dir = getcwd(buf, sizeof(buf));
-  
-#ifdef WIN32
-
-  // This is tricky. Look first for an environment variable. If not
-  // found, try to guess from program name, which if we've been
-  // launched using file associations, will contain the full
-  // executable path. This should make things work without having to
-  // do and "install"
-
-  if (getenv("SPYVIEW_DIR") != NULL) // otherwise get a windows crash?
-    sharedir = getenv("SPYVIEW_DIR");
-  else 
-    {
-      // Under windows, argv[0] (seems) to get the full program path
-      // (when launched by explorer.exe, but not when called from the
-      // cmd.exe command line) So we try to split out the path to the
-      // executable here.
-      sharedir = argv[0]; 
-      int c2 = sharedir.find_last_of("\\");
-      if(c2 >= 0)
-       sharedir.replace(c2,string::npos, "");
-      info("SPYVIEW_DIR not found: guessing %s from argv[0]\n", sharedir.c_str());
-    }
-  if (sharedir.size() == 0)
-    {
-      warn("Could not find good sharedir: reverting to '.'\n");
-      sharedir = ".";
-    }
-  info("sharedir is %s\n", sharedir.c_str());
-
-  // For win32, we have a couple of options to get the user's
-  // Application Data directory: APPDATA, USERPROFILE, or HOMEDRIVE +
-  // HOMEPATH + "Application Data\".  For local users, these are all
-  // the same.  For network users, they can be different: for example,
-  //
-  // HOMEPATH=\ HOMEDRIVE=H:  
-
-  // USERPROFILE=C:\Documents and Settings\gsteele
-  // APPDATA=\\tudelft.net\staff-homes\S\gsteele\Application Data
-  //
-  // Ideally, we should store it on the network drive H:
-  // (\\tudelft.net\staff-homes\S\gsteele\). However, if we just use
-  // APPDATA, it will not work since mingw32 does not support DFS UNC
-  // paths. (It does support regular UNC paths, such as
-  // \\myserver\gsteele, although forward slashes are not interpreted
-  // as directory separators, as they are for local dirctories on
-  // WinXP).
-  //
-  // In the end, it seems to be safest to take HOMEDRIVE + HOMEPATH + "Application Data"
-
-  // Update: 3 Dec 09
-  //
-  // Due to popular demand, I will now change the default behaviour so
-  // that spyview uses the settings files that are in the SHAREDIR,
-  // unless there is a SPYVIEW_PREF_DIR set. Note that from the
-  // command line, you will need to set SPYVIEW_PREF_DIR.
-  
-  if(getenv("SPYVIEW_PREF_DIR") != NULL)
-      userdir = getenv("SPYVIEW_PREF_DIR");
-  //else if((getenv("HOMEDRIVE") != NULL) && (getenv("HOMEPATH") != NULL))
-  //{
-  //  userdir = getenv("HOMEDRIVE");
-  //  userdir = userdir + getenv("HOMEPATH") + "\\Application Data";
-  //  userdir += "\\spyview"; 
-  //}
-  else
-    userdir=sharedir;
-  info("userdir is %s\n", userdir.c_str());
-
-#else
-  if(getenv("HOME"))
-    userdir = getenv("HOME");
-  else
-    userdir = ".";
-  userdir += "/.spyview";
-  sharedir = SPYVIEW_DATADIR;
-#endif
-  default_file = sharedir + DIRECTORY_SEPARATOR + "default_image.pgm";
-  
-  info("def file is %s\n", default_file.c_str());
-
-  string settings_file("");
-
-  int firstarg;         
-  Fl::args(argc,argv,firstarg);
-
-  init_spypal();
-  colormap_callback = spypal_cb;
-  spypal_sharedir = sharedir;
-  while ((c = getopt(argc, argv, "s:")) != -1)
-    {
-      switch (c)
-       {
-       case 's':
-         info("found settings file %s\n", optarg);
-         settings_file = userdir + DIRECTORY_SEPARATOR + "settings" + DIRECTORY_SEPARATOR + optarg;
-         break;
-       }
-    }
-  
-  //info("settings file %s\n", settings_file.c_str());
-  //getchar();
-
-  make_window();
-
-  // Initialize the optional "modules"; these insert themselves into spyview callbacks to grab
-  // keystrokes and draw things.
-
-  LineDraw iwld(iw);
-  Fitting  iwf(iw);
-  ThresholdDisplay iwtd(iw);
-  Fiddle iwfiddle(iw);
-
-  // Set the pointers to the controls window and the process_queue in the image window class
-  iw->controls_window = control;
-  iw->process_queue = pqueue;
-  iw->external_update = update_widgets;
-  iw->drag_n_drop = load_filech;
-
-  embed_colormap();
-
-  iw->setGamma(1.0,0.0);
-  wpbox->value(iw->wpercent);
-  bpbox->value(iw->bpercent);
-
-  //add_image_operations(); // why doesn't this work? must be something funny with the macros...
-
-  Define_Image_Operation(new Image_Operation("neg","Negate numerical data"));
-  Define_Image_Operation(new Image_Operation("square","Average pixels to make a square image"));
-  Define_Image_Operation(new Image_Operation("autoflip","Flip axes so that more neg end is on left/bottom"));
-
-  Image_Operation sub_fitplane("sub fitplane","Subtract a fitted plane with outlier rejection");
-  sub_fitplane.addParameter("Low ", 20.0);
-  sub_fitplane.addParameter("High ", 20.0);
-  sub_fitplane.addParameter("!Percentiles?", 1);
-  Define_Image_Operation(&sub_fitplane);
-
-  Image_Operation sub_plane("sub plane","Subtract a plane with a specified slope");
-  sub_plane.addParameter("Vert %", 0.0);
-  sub_plane.addParameter("Horiz  %", 0.0);
-  Define_Image_Operation(&sub_plane);
-
-  Image_Operation scale_axes("scale axes","Scale the ranges of the X & Y axes");
-  scale_axes.addParameter("X scale", 1.0);
-  scale_axes.addParameter("Y scale", 1.0);
-  Define_Image_Operation(&scale_axes);
-
-  Image_Operation offset_axes("offset axes","Offset the ranges of the X & Y axes");
-  offset_axes.addParameter("X offset", 0.0);
-  offset_axes.addParameter("Y offset", 0.0);
-  Define_Image_Operation(&offset_axes);
-
-  Image_Operation interp("interp","Interpolate the data onto a new grid (bilinear)");
-  interp.addParameter("New x size", 200);
-  interp.addParameter("New y size", 200);
-  Define_Image_Operation(&interp);
-
-  Image_Operation scale_img("scale img","Scale the image data using bilinear interpolation");
-  scale_img.addParameter("X scaling", 2.5);
-  scale_img.addParameter("Y scaling", 2.5);
-  Define_Image_Operation(&scale_img);
-
-    Image_Operation sub_lbl("sub lbl", "Subtract the mean of each image line with outlier rejection");
-  sub_lbl.addParameter("Low %", 2.0);
-  sub_lbl.addParameter("High %", 90.0);
-  sub_lbl.addParameter("Low limit", -1e99);
-  sub_lbl.addParameter("High limit", 1e99);
-  //sub_lbl.addParameter("!Whole image thr?", 0);
-  //sub_lbl.addParameter("!Percentiles?", 1);
-  Define_Image_Operation(&sub_lbl);
-
-  Image_Operation sub_cbc("sub cbc","Subtract the mean of each image column with outlier rejection");
-  sub_cbc.addParameter("Low ", 2.0);
-  sub_cbc.addParameter("High ", 90.0);
-  sub_cbc.addParameter("Low limit", -1e99);
-  sub_cbc.addParameter("High limit", 1e99);
-  //sub_cbc.addParameter("!Whole image thr?", 0);
-  //sub_cbc.addParameter("!Percentiles?", 1);
-  Define_Image_Operation(&sub_cbc);
-
-  Image_Operation sub_line("sub linecut","Subtract a linecut from every line");
-  sub_line.addParameter("Line Num",0);
-  sub_line.addParameter("!Horizontal",1);
-  sub_line.addParameter(".Current Line",0,cb_sub_current_line);
-  Define_Image_Operation(&sub_line);
-
-  Image_Operation outlier_line("outlier","Remove an outlier line from the data");
-  outlier_line.addParameter("Line Num",0);
-  outlier_line.addParameter("!Horizontal",1);
-  outlier_line.addParameter(".Current Line",0,cb_sub_current_line);
-  Define_Image_Operation(&outlier_line);
-
-  Define_Image_Operation(new Image_Operation("xderiv","Take an x derivative of the image data"));
-  Define_Image_Operation(new Image_Operation("yderiv","Take a y derivative of the image data"));
-  Image_Operation ederiv("ederiv","Take an energy derivative of the image data");
-  ederiv.addParameter("Negative Scale",1.0);
-  ederiv.addParameter("Positive Scale",1.0);
-  Define_Image_Operation(&ederiv);
-
-  Image_Operation dderiv("dderiv", "Take a derivative along an arbitrary axis");
-  dderiv.addParameter("Theta",0.0);
-  Define_Image_Operation(&dderiv);
-  Image_Operation gradmag("gradmag", "Take the magnitude of the gradient");
-  gradmag.addParameter("Axis Bias [0-1.0]",0.5);
-  Define_Image_Operation(&gradmag);
-
-  Image_Operation gamma("power","y = x^p, p<0 & abs(x)<eps => truncate x, y<0 & p not int => set y=0"); // a better name
-  gamma.addParameter("Power", 0.5);
-  gamma.addParameter("Epsilon", 1e-20);
-  Define_Image_Operation(&gamma);
-
-  Define_Image_Operation(new Image_Operation("norm lbl","Stretch the contrast of each line to full scale"));
-  Define_Image_Operation(new Image_Operation("norm cbc","Stretch the contrast of each column to full scale"));
-
-  Image_Operation lp("lowpass","Low pass filter the image; 0 for no filtering");
-  lp.addParameter("X Width",3.0);
-  lp.addParameter("Y Width",3.0);
-  lp.addParameter("?Type 0,Gaussian 1,Lorentzian 2,Exponential 3,Thermal",0.0);
-  Define_Image_Operation(&lp);
-
-  Image_Operation hp("highpass","High pass filter the image; 0 for no filtering");
-  hp.addParameter("X Width",3.0);
-  hp.addParameter("Y Width",3.0);
-  hp.addParameter("Pass. %",0.0);
-  hp.addParameter("?Type 0,Gaussian 1,Lorentzian 2,Exponential",0.0);
-  Define_Image_Operation(&hp);
-
-  Image_Operation notch("notch","Notch filter the image; 0 for no filtering");
-  notch.addParameter("X Low",2.0);
-  notch.addParameter("X High",2.0);
-  notch.addParameter("Y Low",2.0);
-  notch.addParameter("Y High",3.0);
-  Define_Image_Operation(&notch);
-
-  Image_Operation despeckle("despeckle","Despeckle Image Using Median Filter");
-  despeckle.addParameter("!X Despeckle",1);
-  despeckle.addParameter("!Y Despeckle",0);
-  Define_Image_Operation(&despeckle);
-
-  Image_Operation flip("flip","Flip the Image");
-  flip.addParameter("!Flip X Axis",0);
-  flip.addParameter("!Flip Y Axis",0);
-  Define_Image_Operation(&flip);
-
-  Image_Operation crop("crop","Crop the Image (0 to keep current, negative possible for lower/right)");
-  crop.addParameter("left col #", 0);
-  crop.addParameter("right col #", 0);
-  crop.addParameter("upper row #", 0);
-  crop.addParameter("lower row #", 0);
-  crop.addParameter(".Copy Zoom",-1,cb_crop_to_zoom);
-  crop.addParameter(".Reset Zoom",-1,cb_reset_zoom);
-  Define_Image_Operation(&crop);
-
-  Image_Operation pixel_avg("pixel avg","Down sample image by averaging pixels");
-  pixel_avg.addParameter("X pixels", 2);
-  pixel_avg.addParameter("Y pixels", 2);
-  Define_Image_Operation(&pixel_avg);
-
-  Image_Operation scale("scale data","Scale and center the data (change dynamic range)");
-  scale.addParameter("Factor",0.5);
-  Define_Image_Operation(&scale);
-
-  Image_Operation offset("offset","Add an offset to the data");
-  offset.addParameter("Offset by",0);
-  offset.addParameter("!Auto (sub min first)", 1);
-  Define_Image_Operation(&offset);
-
-  Image_Operation log("log","Take logarithm (base 10) of intensities");
-  log.addParameter("!Auto subtract offset", 0);
-  log.addParameter("New min",1e-4);
-  Define_Image_Operation(&log);
-
-  Image_Operation sw_find("rm switch", "Remove switches (1 pixel jumps) in the data");
-  sw_find.addParameter("Threshold", 300);
-  sw_find.addParameter("Avg win",10);
-  Define_Image_Operation(&sw_find);
-
-  Image_Operation even_odd("even odd","Extract even or odd rows, optionally flipping odd rows");
-  even_odd.addParameter("!Even", 1);
-  even_odd.addParameter("!Flip odd rows", 1);
-  Define_Image_Operation(&even_odd);
-
-  Image_Operation hist2d("hist2d", "Convert y-axis into a histogram of each column");
-  hist2d.addParameter("ymax", -100);
-  hist2d.addParameter("ymax", +100);
-  hist2d.addParameter("Num bins", 100);
-  hist2d.addParameter(".Autorange", -1, cb_hist2d_autorange);
-  //hist2d.addParameter("!Flip odd rows", 1);
-  Define_Image_Operation(&hist2d);
-
-
-  Image_Operation shift_data("shift data","Horizontally shift data after a given row");
-  shift_data.addParameter("After row", 0);
-  shift_data.addParameter("Shift (pix)", 0);
-  Define_Image_Operation(&shift_data);
-
-  Image_Operation remove_lines("remove lines","Remove lines, shifting data vertically");
-  remove_lines.addParameter("Start row", 0);
-  remove_lines.addParameter("# lines", 0);
-  Define_Image_Operation(&remove_lines);
-
-  Define_Image_Operation(new Image_Operation("rotate cw","Rotate the image by 90 degrees clockwise"));
-  Define_Image_Operation(new Image_Operation("rotate ccw","Rotate the image by 90 degrees counter clockwise"));
-  Define_Image_Operation(new Image_Operation("abs","Take the absolute value of the intensities"));
-  Define_Image_Operation(new Image_Operation("equalize","Perform a histogramic equalization on the image"));
-
-  // Now sort image operations alphabetically
-
-
-  // Works on unix, but segfaults on win32?
-
-//   Fl_Browser *b = options;
-//   for ( int t=1; t<=b->size(); t++ ) {
-//     for ( int r=t+1; r<=b->size(); r++ ) {
-//       if ( strcmp(b->text(t), b->text(r)) > 0 ) {
-//     b->swap(t,r);
-//       }
-//     }
-//   }
-
-   Fl_Browser *b = options;
-   for ( int t=1; t<=b->size(); t++ ) 
-     {
-     for ( int r=t+1; r<=b->size(); r++ ) 
-       {
-       if ( strcmp(b->text(t), b->text(r)) > 0 ) 
-        {
-          //b->swap(t,r);
-          string tmp = b->text(t);
-          void *ptr = b->data(t);
-          b->text(t, b->text(r));
-          b->data(t, b->data(r));
-          b->text(r, tmp.c_str());
-          b->data(r, ptr);
-        }
-       }
-     }
-
-  
-
-  // Check if these swapped properly
-//   Image_Operation *op = (Image_Operation *) b->data(1);
-//   info("text %s\n", options->text(1));
-//   info("name %s\n", op->name.c_str());
-  
-  // Now it works fine? I don't know why it wasn't working?
-
-  arg_values = argv;
-  arg_count = argc;
-  opt_index = optind;
-
-  load_orig_files();
-
-  info("Found "_STF" files\n", filenames.size());
-
-  // Construct a list of colormap files
-  // First scan them from /usr/share/spyview/cmaps, then ~/cmaps/ under unix
-  // Look in current directory, then location of .exe / cmaps under windows.
-
-  string user_path = userdir + DIRECTORY_SEPARATOR + "cmaps" + DIRECTORY_SEPARATOR;
-  string share_path = sharedir +  DIRECTORY_SEPARATOR + "cmaps" + DIRECTORY_SEPARATOR;
-  find_cmaps(share_path, "");
-  info("Loaded "_STF" color maps from %s.\n",cmapfiles.size(),share_path.c_str());
-
-  if(share_path != user_path)
-    {
-      find_cmaps(user_path, "~/");  
-      info("Loaded "_STF" color maps from %s.\n",cmapfiles.size(),user_path.c_str());
-    }
-
-  int ind = cmapch->add("Custom",0,0,-1);
-  cmapch->menu()[ind].labelfont(FL_HELVETICA_BOLD); // Make spypal stand out as it's different.
-
-  // Update some of the widgets with the default values from the ImageWindow class
-  gpusing->value(iw->gp_using_string);
-  gpwith->value(iw->gp_with_string.c_str());
-  location_fmt->value("%.1f");
-
-#ifdef WIN32
-  Gnuplot_Interface::gnuplot_cmd = "\"" + sharedir + "\\pgnuplot.exe\"";
-#endif
-
-  // Load the first file
-  filech->value(0);
-
-  // Find the first valid cmap
-  for(int n = 0; true; n++)
-    {
-      assert(n <= cmapch->size());
-      cmapch->value(n);
-      if (!cmapch->mvalue()->submenu() && cmapch->text(n) != NULL) // null entry at end of submenu
-       break;
-    }
-
-  //filech->do_callback(filech, (void *)argv[1]);
-  //normb->do_callback();
-  Fl::add_handler(keyhandler);
-  //control->show();
-  iw->statusCallback = Update_Status_Bar;
-  // load the colormap
-  loadsettings(settings_file.c_str());
-  // Both of these are now called by loadsettings so we don't load the file twice at startup
-  //cmapch->do_callback();
-  //filech->do_callback();  // load the file before we call show
-  Fl_Text_Buffer *helpbuf = new Fl_Text_Buffer();
-  help_text->buffer(helpbuf);
-  string help_file = sharedir + DIRECTORY_SEPARATOR + "help.txt";
-  info("loading help from file %s\n", help_file.c_str());
-  helpbuf->loadfile(help_file.c_str());
-  helpbuf->append("\nBuild stamp:\n\n");
-  helpbuf->append(BUILDSTAMP);
-  iw->callback(close_window_callback);
-  iw->show(argc,argv);
-
-  Fl::run();
-
-  delete iw; // Make sure we clean up the gnuplot nicely.
-}
-
-int keyhandler(int event)
-{
-  int key;
-  int n;
-
-  switch (event)
-    {
-    case FL_SHORTCUT:
-      key = Fl::event_key();
-      switch(key)
-       {
-       case 'd':
-         if (Fl::event_state() & FL_SHIFT)
-           loadImageProcessing();
-         else if (Fl::event_state() & FL_CTRL)
-           loadColors();
-         else
-           {
-             loadImageProcessing();
-             loadColors();
-           }
-         return 1;
-       case 'e':
-         filech->do_callback();
-         return 1;
-       case 'u':
-         if (unitswin->shown())
-           unitswin->hide();
-         else
-           unitswin->show();
-         return 1;
-       case 'c':
-         if (Fl::event_state() & FL_CTRL)
-           {
-             if (location_window->shown())
-               location_window->hide();
-             else
-               location_window->show();
-             return 1;
-           }
-         // note falling case!!!
-       case FL_Escape:
-         //also for 'c' with no shift
-         if(!(iw->line_cut_limit & NOLINE))
-           return 1;
-         iw->line_cut_type = NOLINE;
-         iw->plotLineCut();
-         iw->redraw();
-         return 1;
-       case FL_Right:
-       case ' ':
-         n = filech->value();
-         while (true)
-           {
-             n++;
-             if (n == filech->size() - 1)
-               n=0;
-             if (filech->text(n) != NULL && strcmp(filech->text(n), "More") != 0)
-               break;
-           }
-         filech->value(n);
-         filech->do_callback();
-         return 1;
-       case FL_Left:
-       case FL_BackSpace:
-         n = filech->value();
-         while (true)
-           {
-             n--;
-             if (n<0)
-               n = filech->size()-1;
-             if (filech->text(n) != NULL && strcmp(filech->text(n), "More") != 0)
-               break;
-           }
-         filech->value(n);
-         filech->do_callback();
-         return 1;
-       case FL_Down:
-       case 'j':
-         n = cmapch->value();
-         while (true)
-           {
-             n++;
-             if (n == cmapch->size()-1)
-               n=0;
-             cmapch->value(n);
-             if (!cmapch->mvalue()->submenu() && cmapch->text(n) != NULL) // null entry at end of submenu
-               break;
-           }
-         cmapch->do_callback();
-         return 1;
-       case FL_Up:
-       case 'k':
-         n = cmapch->value();
-         while (true)
-           {
-             n--;
-             if (n<0)
-               n= cmapch->size()-1;
-             cmapch->value(n);
-             if (!cmapch->mvalue()->submenu() && cmapch->text(n) != NULL)
-               break;
-           }
-         cmapch->do_callback();
-         return 1;
-       case 't':
-         showUsedFiles(Fl::event_state() & FL_SHIFT);
-         break;
-       case 'n':
-         if (Fl::event_state() & FL_SHIFT)
-           {
-             Add_Image_Operation(new Image_Operation("neg", "Negate numerical data"));
-             reload_data();
-             pqueue->select(pqueue->size());
-             pqueue->do_callback();
-             return 1;
-           }
-         else 
-           {
-             normb->do_callback();
-             return 1;
-           }
-       case 'q':
-         spyview_exit();
-         return 1; // note that this is required if we're exiting by hiding all the windows!!!!
-       case 's':
-         iw->exportMTX(true);
-         return 1;
-       case 'v':
-         if (control->visible())
-           control->hide();
-         else
-           control->show();
-         return 1;
-       case 'h':
-         if (helpwin->visible())
-           helpwin->hide();
-         else
-           helpwin->show();
-         return 1;
-       case 'o':
-         if (normwin->visible())
-           normwin->hide();
-         else
-           normwin->show();
-         return 1;
-       case 'x':
-         xsecb->do_callback();
-         return 1;
-       case 'f':
-         if (!(Fl::event_state() & FL_CTRL) &&
-             !(Fl::event_state() & FL_SHIFT))
-           {
-             if (iw->pfc.win->visible())
-               iw->pfc.win->hide();
-             else
-               iw->pfc.win->show();
-             return 1;
-           }
-       case 'l':
-         if (Fl::event_state() & FL_CTRL)
-           {
-             if (reload_window->shown())
-               reload_window->hide();
-             else
-               reload_window->show();
-             return 1;
-           }
-       case 'r':
-         iw->setXZoom(1);
-         iw->setYZoom(1);
-         return 1;
-       case 'p':
-         if (Fl::event_state() & FL_CTRL)
-           {
-             iw->setupPS();
-             return 1;
-           }
-         else if (Fl::event_state() & FL_ALT)
-           {
-             info("exporting postscript\n");
-             iw->exportPS();
-             return 1;
-           }
-         else if (Fl::event_state() & FL_SHIFT)
-           {
-             iw->imageprinter->ipc->preview_button->do_callback();
-             return 1;
-           }
-         else
-           {
-             if (procwin->shown())
-               procwin->hide();
-             else
-               procwin->show();
-           }
-         return 1;
-       }   
-    }
-  return 0;
-}
-
-void save_cmap_cb(Fl_Button *o, void*)
-{
-  iw->colormap_window->saveFile();
-}
-
-// Called by spypal to indicate the colormap has changed.
-void spypal_cb()
-{
-  int index = reinterpret_cast<int>(cmapch->mvalue()->user_data());
-  if(index != -1)
-      cmapch->value(cmapch->find_item("Custom"));
-  iw->setColormap(spypal_colormap,spypal_colormap_size);
-}
-
-static bool cmap_is_ppm; // Is the current cmap a ppm file?
-void cmapedit_cb(Fl_Button *, void *)
-{
-  assert(spypal); assert(spypal->win);
-  if(cmap_is_ppm)
-    {
-      printf("CMap is a .ppm; launching import window\n");
-      spypal->copy_cmap(iw->getColormap(), iw->getColormapLength());
-      spypal->import_controls->show();
-      spypal->import_update();
-      cmap_is_ppm = false;
-    }
-  if(spypal->win->visible())
-    spypal->win->hide();
-  else
-    spypal->win->show();
-  colormap_callback();
-}
-
-void cmapch_cb(Fl_Widget *o, void*)
-{
-  FILE *fp;
-  int index;
-
-  index = reinterpret_cast<int>(cmapch->mvalue()->user_data());
-
-  static char label[1024];
-  snprintf(label, 1024, "%s - %s", filech->text(), cmapch->text());
-  iw->label(label);
-  snprintf(label, 1024, "Colormap %s", cmapch->text());
-  (iw->colormap_window)->label(label);
-
-  if(index == -1) // spypal mode!  
-    { // Don't show the spypal win; that's what the edit button's for.
-      //      spypal->win->show(); 
-      spypal_cb();
-      cmap_is_ppm = false;
-      return;
-    }
-
-  assert(index >= 0);
-  assert((unsigned)index < cmapfiles.size());
-
-  //info("userdata for %s is %d\n", cmapch->value(), index);
-  const char *filename = cmapfiles[index].c_str();
-  //info("loading file _%s_ from index %d, text _%s_\n", cmapfiles[index].c_str(), index, cmapch->text(cmapch->value()));
-  spypal->import_controls->hide();
-
-  // File is a spypal colormap
-  if(strstr(filename,".spp") != NULL)
-    {
-      // Don't call spypal_cb; it'll reset the chooser. Hack.
-      colormap_callback = NULL;
-      spypal->load(filename);
-
-      colormap_callback = spypal_cb;
-
-      iw->setColormap(spypal_colormap,spypal_colormap_size);
-      cmap_is_ppm = false;
-      return;
-    }
-
-  cmap_is_ppm = true;
-  spypal->win->hide();
-  pixel **image;
-  pixval maxval;
-  int rows, cols;
-
-  fp = fopen(filename, "rb");
-  if (fp == NULL)
-    {
-      perror(filename);
-      exit(-1);
-    }
-
-#ifndef debug_read //debug a binary read problen in windows. implemented some nice ppm read/write code, will leave it in here.
-  image = ppm_readppm(fp, &cols, &rows, &maxval);
-  fclose(fp);
-
-  uchar newcmap[3*rows];
-  
-  if (cols > 1)
-    error("Invalid colormap %s: must contain only one column!\n", filename);
-  
-  if (maxval != 255)
-    error("Invalid colormap %s: color depth must be 8 bit (255 maxval)\n", filename);
-  
-  for (int i=0; i<rows; i++)
-    {
-      newcmap[i*3] = image[0][i].r;
-      newcmap[i*3+1] = image[0][i].g;
-      newcmap[i*3+2] = image[0][i].b;
-    }
-
-  ppm_freearray(image, rows);
-#else
-  char buf[256];
-  int raw_file = 1;
-
-  fgets(buf, 256, fp);
-  info("_%s_\n", buf);
-  if (strncmp(buf, "P3",2) == 0)
-    raw_file = 0;
-  else if (strncmp(buf, "P6",2) != 0)
-    error("Unsupported magic number %s: %s", buf, filename);
-  fgets(buf, 256, fp);
-  while (buf[0] == '#')
-    fgets(buf, 256, fp);
-  if (sscanf(buf, "%d %d", &cols, &rows) != 2)
-    error("Invalid row/cols in PPM file: %s", filename);
-  if (cols > 1)
-    error("PPM fils should be only 1 pixel wide: %s", filename);
-  fgets(buf, 256, fp);
-  if (sscanf(buf, "%d", &maxval) != 1)
-    error("Invalid maxval in PPM file: %s", filename);
-  if (maxval != 255)
-    error("Only 8 bit (255 maxval) ppm files supported: %s", filename);
-
-  info("reading file %d rows from file %s, raw file %d\n", rows, filename, raw_file);
-  uchar newcmap[3*rows];
-  int n;
-
-  if (raw_file)
-    {
-      if ((n=fread(newcmap, 1, rows*3, fp)) != rows*3)
-       {
-         info("feof %d ferror %d\n", feof(fp), ferror(fp));
-         error("Short read on PPM file (error after %d bytes of %d, offset %x)\n"
-               "last read values %x %x %x %x: %s", 
-               n, rows*3, n, 
-               newcmap[n-4], newcmap[n-3], newcmap[n-2], newcmap[n-1], 
-               filename);
-       }
-    }
-  else
-    {
-      for (int i=0; i<rows; i++)
-       {
-         int r,g,b;
-         if (fgets(buf, 256, fp) == NULL)
-           error("Short read on PPM file (%d of %d): %s", i, rows, filename);
-         if (sscanf(buf, "%d %d %d", &r,&g,&b) != 3)
-           error("Could not convert row %d (%s): %s", i, buf, filename);
-         newcmap[i*3] = r;
-         newcmap[i*3+1] = g;
-         newcmap[i*3+2] = b;
-       }
-    }
-
-#endif
-  iw->setColormap(newcmap, rows);
-}
-
-void filech_cb(Fl_Widget *, void *)
-{
-  int index = reinterpret_cast<int>(filech->mvalue()->user_data());
-  const char *filename = filenames[index].c_str();
-  //info("loading file _%s_ from index %d, text _%s_\n", filename, index, filech->text(filech->value()));
-  int old_w, old_h;
-
-  // Fixme; this leaks memory.
-  char *dir = strdup(filename);
-  dir = dirname(dir);
-  filename = basename(filename);
-  current_filename = filename;
-  if (strcmp(dir, ".") == 0)
-    dir=strdup(original_dir.c_str());
-  info("Changing Directory to: %s\n", dir);
-  info("Filename: %s\n", filename);
-  chdir(dir);
-
-  //info("Qmin/max: %e %e\n", iw->id.qmin, iw->id.qmax);
-
-  // This is a bit awkward due to my naming of the w and h variables
-  // representing the data size, which conflict with the fltk w() and
-  // h() functions returning the window size...
-  old_w = ((Fl_Widget*) iw)->w(); 
-  old_h = ((Fl_Widget*) iw)->h();
-  
-  // All file loading is now handled inside ImageWindow (including mtx). 
-  if (iw->loadData(filename) == -1)
-    {
-      warn("Error with file %s: reverting to default image\n", filename);
-      iw->loadData(default_file.c_str());
-    }
-
-  update_widgets();
-  
-  // Normalize the data if we've been asked
-  if (norm_on_load->value())
-    iw->normalize();
-
-  // Give us a nice label
-  //string label = filename;
-  //label = label + " - " + cmapch->text();
-  //set_units();
-  update_title();
-}
-
-void embed_colormap()
-{
-  control->add(iw->colormap_window);
-
-  iw->colormap_window->resize(colormap_placeholder->x() + Fl::box_dx(colormap_placeholder->box()),
-                             colormap_placeholder->y() + Fl::box_dy(colormap_placeholder->box()),
-                             colormap_placeholder->w() - Fl::box_dw(colormap_placeholder->box()),
-                             colormap_placeholder->h() - Fl::box_dh(colormap_placeholder->box()));
-
-  if(control->visible())
-    iw->show();
-  else
-    iw->colormap_window->set_visible();
-}
-
-void update_title()
-{
-  char buf[256]; 
-  if (iw->id.data3d)
-    snprintf(buf, 256, "%s %.0f (%.3g to %.3g), (%.3g to %.3g)", 
-            current_filename.c_str(), 
-            indexbox->value(),
-            xmin->value(), xmax->value(),
-            ymin->value(), ymax->value());
-  else
-    snprintf(buf, 256, "%s (%.3g to %.3g), (%.3g to %.3g)", 
-            current_filename.c_str(), 
-            xmin->value(), xmax->value(),
-            ymin->value(), ymax->value());
-  iw->copy_label(buf);
-}
-
-void set_units()
-{
-  // First update image data class
-  iw->id.xmin = xmin->value();
-  iw->id.xmax = xmax->value();
-  iw->id.ymin = ymin->value();
-  iw->id.ymax = ymax->value();
-  iw->id.xname = xunitname->value();
-  iw->id.yname = yunitname->value();
-  iw->id.zname = zunitname->value();
-
-  // Note: changing these doesn't make any sense!
-  // These should now be manipulated through imageprocessing operations
-  // that act on the image data matrix
-  //iw->id.zmin = zmin->value();
-  //iw->id.zmax = zmax->value();
-
-  // Now update the mtx data class if we have data loaded
-
-  int x,y;
-  if (iw->id.data3d)
-    {
-      switch (dim->value())
-       {
-       case 0:  // YZ
-         x = 1; 
-         y = 2;
-         break;
-       case 1: // ZX
-         x = 2;
-         y = 0;
-         break;
-       case 2: // XY
-         x = 0;
-         y = 1;
-         break;
-       }
-      iw->id.mtx.axismin[x] = xmin->value();
-      iw->id.mtx.axismax[x] = xmax->value();
-      iw->id.mtx.axismin[y] = ymin->value();
-      iw->id.mtx.axismax[y] = ymax->value();
-      iw->id.mtx.axisname[x] = xunitname->value();
-      iw->id.mtx.axisname[y] = yunitname->value();
-      iw->id.mtx.dataname = zunitname->value();
-    }
-
-  update_widgets();
-  iw->plotLineCut();
-  update_title();
-}
-
-void set_3d_units()
-{
-  iw->id.mtx.axismin[0] = mtx_xmin->value();
-  iw->id.mtx.axismin[1] = mtx_ymin->value();
-  iw->id.mtx.axismin[2] = mtx_zmin->value();
-  iw->id.mtx.axismax[0] = mtx_xmax->value();
-  iw->id.mtx.axismax[1] = mtx_ymax->value();
-  iw->id.mtx.axismax[2] = mtx_zmax->value();
-  iw->id.mtx.axisname[0] = mtx_xname->value();
-  iw->id.mtx.axisname[1] = mtx_yname->value();
-  iw->id.mtx.axisname[2] = mtx_zname->value();
-
-  // We also have to update the image window class
-  
-  int x,y;
-  switch (dim->value())
-    {
-    case 0:  // YZ
-      x = 1; 
-      y = 2;
-         break;
-    case 1: // ZX
-      x = 2;
-      y = 0;
-      break;
-    case 2: // XY
-      x = 0;
-      y = 1;
-      break;
-    }
-
-  iw->id.xmin = iw->id.mtx.axismin[x];
-  iw->id.xmax = iw->id.mtx.axismax[x];
-  iw->id.ymin = iw->id.mtx.axismin[y];
-  iw->id.ymax = iw->id.mtx.axismax[y];
-  iw->id.xname = iw->id.mtx.axisname[x];
-  iw->id.yname = iw->id.mtx.axisname[y];
-
-  update_widgets();
-  iw->plotLineCut();
-}
-  
-
-void saveb_cb(Fl_Widget *, void *)
-{
-  iw->saveFile();
-  //fl_message("File was saved to %s", savebox->value());
-  fl_beep(FL_BEEP_MESSAGE);
-}
-
-void update_widgets()
-{
-  int min, max, width, center;
-  min = iw->hmin;
-  max = iw->hmax;
-  width = (max - min);
-  center = (max + min)/2;
-  
-  minv->value(min);
-  minslider->value(min);
-  minroller->value(min);
-  minv_units->value(iw->id.quant_to_raw(min));
-
-  maxv->value(max);
-  maxslider->value(max);
-  maxroller->value(max);
-  maxv_units->value(iw->id.quant_to_raw(max));
-
-  centerv->value(center);
-  centerslider->value(center);
-  centerroller->value(center);
-  centerv_units->value(iw->id.quant_to_raw(center));
-
-  widthv->value(width);
-  widthslider->value(width);
-  widthroller->value(width);
-  widthv_units->value(iw->id.quant_to_raw(width)-iw->id.quant_to_raw(0));
-
-  gammav->value(iw->gam);
-  gammaroller->value(log(iw->gam));
-  gammaslider->value(log(iw->gam));
-  gcenterv->value(iw->gcenter);
-  gcenterroller->value(iw->gcenter);
-  gcenterslider->value(iw->gcenter);
-  iw->adjustHistogram();
-  plothistb->do_callback();
-  plotcmapb->do_callback();
-
-  plotcmapb->value(iw->plot_cmap);
-  plothistb->value(iw->plot_hist);
-  invertb->value(iw->invert);
-  negateb->value(iw->negate);
-  savebox->value(iw->output_basename);
-  
-  plane_a->value(iw->plane_a*((double)iw->h/65535.0));
-  plane_aroller->value(iw->plane_a*((double)iw->h/65535.0));
-  plane_aslider->value(iw->plane_a*((double)iw->h/65535.0));
-  plane_b->value(iw->plane_b*((double)iw->w/65535.0));
-  plane_broller->value(iw->plane_b*(double)iw->w/65535.0);
-  plane_bslider->value(iw->plane_b*((double)iw->w/65535.0));
-
-  cmap_min->value(iw->cmap_min);
-  cmap_max->value(iw->cmap_max);
-
-  xzoom_value->value(iw->xzoom);
-  yzoom_value->value(iw->yzoom);
-
-  xsize->value(iw->w);
-  ysize->value(iw->h);
-
-  // Update the units window
-
-  xunitname->value(iw->id.xname.c_str());
-  yunitname->value(iw->id.yname.c_str());
-  zunitname->value(iw->id.zname.c_str());
-
-  //qinfo("zname update: %s\nq", iw->id.zname.c_str());
-
-  xmin->value(iw->id.xmin);
-  ymin->value(iw->id.ymin);
-  zmin->value(iw->id.qmin);
-
-  xmax->value(iw->id.xmax);
-  ymax->value(iw->id.ymax);
-  zmax->value(iw->id.qmax);
-
-  gpusing->value(iw->gp_using_string);
-  gpwith->value(iw->gp_with_string.c_str());
-  
-  axis_type->value(iw->lc_axis);
-
-  // Update the load settings window
-
-  gp_parse_txt->value(iw->id.mtx.parse_txt);
-  gp_delft_raw->value(iw->id.mtx.delft_raw_units);
-  gp_delft_set->value(iw->id.mtx.delft_settings);
-  gp_col->value(iw->id.gp_column+1);
-  a_quant_percent->value(iw->id.auto_quant_percent);
-
-  qmin->value(iw->id.qmin);
-  qmax->value(iw->id.qmax);
-
-  if (iw->id.data3d)
-    {
-      controls3d->activate();
-      units3d->activate();
-    }
-  else
-    {
-      controls3d->deactivate();
-      units3d->deactivate();
-    }
-
-  if (iw->id.datfile_type == MATRIX)
-    dat_type_mat->setonly();
-  else if (iw->id.datfile_type == GNUPLOT)
-    dat_type_gp->setonly();
-  else if (iw->id.datfile_type == DELFT_LEGACY)
-    dat_type_delft->setonly();
-  else if (iw->id.datfile_type == DAT_META)
-    dat_type_meta->setonly();
-  
-  //info("update: type is %d\n", iw->id.gpload_type);
-  if (iw->id.gpload_type == COLUMNS)
-    gp_type_col->setonly();
-  else if (iw->id.gpload_type == INDEX)
-    gp_type_index->setonly();
-
-  if (iw->window_size_action == KEEPZOOM)
-    keep_zoom->setonly();
-  else if (iw->window_size_action == KEEPSIZE)
-    keep_size->setonly();
-  else // if (iw->window)_size_action == RESETZOOM)
-    reset_zoom->setonly();
-  
-  if (iw->id.auto_quant)
-    a_quant->setonly();
-  else 
-    man_quant->setonly();
-
-  // Update MTX dialog boxes
-
-  indexbox->value(iw->id.mtx_index);
-  indexslider->value(iw->id.mtx_index);
-  indexroller->value(iw->id.mtx_index);
-  
-  indexbox->maximum(iw->id.mtx.size[iw->id.mtx_cut_type]-1);
-  indexslider->maximum(iw->id.mtx.size[iw->id.mtx_cut_type]-1);
-  indexroller->maximum(iw->id.mtx.size[iw->id.mtx_cut_type]-1);
-
-  index_value->value(iw->id.mtx.get_coordinate(iw->id.mtx_cut_type,
-                                              iw->id.mtx_index));
-
-  dim->value((int)iw->id.mtx_cut_type);
-  mtx_label->value(iw->id.do_mtx_cut_title);
-
-  mtx_x->value(iw->id.mtx.size[0]);
-  mtx_y->value(iw->id.mtx.size[1]);
-  mtx_z->value(iw->id.mtx.size[2]);
-
-  mtx_xmin->value(iw->id.mtx.axismin[0]);
-  mtx_ymin->value(iw->id.mtx.axismin[1]);
-  mtx_zmin->value(iw->id.mtx.axismin[2]);
-
-  mtx_xmax->value(iw->id.mtx.axismax[0]);
-  mtx_ymax->value(iw->id.mtx.axismax[1]);
-  mtx_zmax->value(iw->id.mtx.axismax[2]);
-
-  mtx_xname->value(iw->id.mtx.axisname[0].c_str());
-  mtx_yname->value(iw->id.mtx.axisname[1].c_str());
-  mtx_zname->value(iw->id.mtx.axisname[2].c_str());
-
-  xrange->value(iw->line_cut_xauto);
-
-}
-
-void Fetch_ProcWindow_Settings(Image_Operation *op)
-{
-  for(unsigned i = 0; i < op->parameters.size(); i++)
-    {
-      Image_Operation::Parameter *p = &(op->parameters[i]);
-      if(i > proc_bool_parameters.size()) // All buttons must be at end.
-       {
-         assert(p->name.c_str()[0] == '.');
-         break;
-       }
-
-      Fl_Check_Button *b = proc_bool_parameters[i];
-      Fl_Input *in = proc_parameters[i];
-      Fl_Choice *ch = proc_choice_parameters[i];
-      switch(p->name.c_str()[0])
-       {
-       case '!':
-         p->value = b->value();
-         break;
-       case '?':
-         p->value = reinterpret_cast<int>(ch->mvalue()->user_data_);
-         break;
-       case '.':
-         p->value = 0;
-         break;
-       default:
-         p->value = atof(in->value());
-         break;
-       }
-    }
-  if(last_proc_side == pqueue)
-    op->enabled = enable_filter->value();
-}
-
-void Set_ProcWindow_Settings(Image_Operation *op)
-{
-  bool redraw_window = false;
-  int bcount = 0;  // Number of buttons so far.
-  assert(proc_bool_parameters.size() == proc_parameters.size());
-  assert(proc_choice_parameters.size() == proc_parameters.size());
-
-  for(unsigned i = 0; i < proc_button_parameters.size(); i++)
-    {
-      Fl_Button *but = proc_button_parameters[i];
-      but->hide();
-      but->callback( (Fl_Callback *) NULL,NULL);
-    }
-  for(unsigned i = 0; i < op->parameters.size(); i++)
-    {
-      Image_Operation::Parameter *p = &(op->parameters[i]);
-      if(p->name.c_str()[0] == '.') // Button
-       {
-         assert(bcount < proc_button_parameters.size());
-         Fl_Button *but = proc_button_parameters[bcount++];
-         but->label(p->name.c_str()+1);
-         but->value(static_cast<int>(p->value));
-         if(p->cb)
-           but->callback(p->cb,NULL);
-         but->show();
-         continue;
-       }
-
-      assert(op->parameters.size() > i-bcount);
-      Fl_Check_Button *b = proc_bool_parameters[i-bcount];
-      Fl_Input *in = proc_parameters[i-bcount];
-      Fl_Choice *ch = proc_choice_parameters[i-bcount];
-      switch(p->name.c_str()[0])
-       {
-       case '.':
-         assert(0);
-       case '!': // Boolean
-         {
-           if(strcmp(p->name.c_str()+1,b->label()) != 0)
-             redraw_window = true;
-           b->label(p->name.c_str()+1);
-           b->value(static_cast<int>(p->value));
-           b->show();
-           in->hide();
-           ch->hide();
-           break;
-         }
-       case '?': // Choice
-         {
-           redraw_window = true; // Lazy lazy lazy
-           char *tmp = strdup(p->name.c_str());
-           char *s1 = strchr(tmp,' ');
-           assert(s1 != NULL);
-           *s1++ = 0; // tmp+1 is now the choice name
-           if(strcmp(tmp+1,ch->label()) != 0)
-             redraw_window = true;
-           ch->copy_label(tmp+1);
-           ch->clear();
-           while(isspace(*s1))
-             s1++;
-           while(1)
-             {
-               char *s2 = strchr(s1,' ');
-               if(s2 != NULL)
-                 *s2 = 0;
-               char buf[1024];
-               int val;
-               if(sscanf(s1," %d,%s ",&val,buf) != 2)
-                 {
-                   fprintf(stderr,"Error parsing format string \"%s\" from %s\n",s1,p->name.c_str());
-                   exit(1);
-                 }
-               int idx = ch->add(buf,(const char *)NULL,NULL,(void *)val);
-               if(val == p->value)
-                 ch->value(idx);
-               if(s2 == NULL)
-                 break;
-               else 
-                 s1 = s2+1;
-             }
-           b->hide();
-           in->hide();
-           ch->show();
-           free(tmp);
-           break;
-         }
-       default:
-         {
-           if(p->name != in->label())
-             redraw_window = true;
-           in->label(p->name.c_str());
-           char buf[1024];
-           snprintf(buf,sizeof(buf),"%g",p->value);
-           in->value(buf);
-           in->show();
-           b->hide();
-           ch->hide();
-           break;
-         }
-       }
-    }
-  for(unsigned i = op->parameters.size()-bcount; i < proc_parameters.size(); i++)
-    {
-      proc_parameters[i]->hide();
-      proc_bool_parameters[i]->hide();
-      proc_choice_parameters[i]->hide();
-    }
-  proc_description->value(op->description.c_str());
-  if(last_proc_side == pqueue)
-    {
-      enable_filter->value(op->enabled);
-      enable_filter->activate();
-    }
-  else
-    enable_filter->deactivate();  
-  if(redraw_window) // Sometimes, if the labels get longer, we get dead characters in the background.
-    procwin->redraw();
-}
-
-void Define_Image_Operation(Image_Operation *op)
-{
-  options->add(op->name.c_str(), op);
-}
-
-void Add_Image_Operation(Image_Operation *op)
-{
-  info("Adding operation: %s\n", op->name.c_str());
-  Image_Operation *new_op = new Image_Operation(*op); // Copy so we don't share settings.
-  pqueue->add(op->name.c_str(), new_op);
-}
-
-void Update_Status_Bar(int key, bool down)
-{
-  static double ox, oy;
-
-  int i = iw->dounzoom(Fl::event_x(),iw->xzoom);
-  int j = iw->dounzoom(Fl::event_y(),iw->yzoom);
-
-  double x = iw->id.getX(i);
-  double y = iw->id.getY(j);
-                        
-  if(ox != x || oy != y)
-    {
-      static char locbuf[1024];
-      static char tmpbuf[1024];
-      static char fmt_string[1024];
-      static char fmt[1024];
-
-      // Format is set in the Cursor Position window
-      snprintf(fmt, sizeof(fmt), "%s", location_fmt->value());
-
-      // Update the location bar at the bottom of the controls window
-      sprintf(fmt_string, "%s,%s = %s %%s", fmt, fmt, fmt);
-      snprintf(locbuf,sizeof(locbuf),fmt_string, 
-              x,y,iw->dataval(i,j), iw->id.zname.c_str());
-      location_bar->label(locbuf);
-
-      // Update the "Cursor Postion" window as well
-      snprintf(tmpbuf, sizeof(tmpbuf), fmt, x);
-      location_x->value(tmpbuf);
-      location_x->label(xunitname->value());
-      x_col->value(i);
-
-      snprintf(tmpbuf, sizeof(tmpbuf), fmt, y);
-      location_y->value(tmpbuf);
-      location_y->label(yunitname->value());
-      y_row->value(j);
-
-      snprintf(tmpbuf, sizeof(tmpbuf), fmt, iw->dataval(i,j));
-      location_data->value(tmpbuf);
-      data_name->value(zunitname->value());
-
-      // Update the zoom window information in the Cursor window
-
-      if (iw->zoom_window)
-       {
-         zoom_group->activate();
-         int x1,y1,x2,y2;
-         iw->zoom_window->getSourceArea(x1,y1,x2,y2);
-         
-         zx1->value(x1); 
-         snprintf(tmpbuf, sizeof(tmpbuf), fmt, iw->id.getX(x1));
-         zx1v->value(tmpbuf);
-
-         zx2->value(x2); 
-         snprintf(tmpbuf, sizeof(tmpbuf), fmt, iw->id.getX(x2));
-         zx2v->value(tmpbuf);
-         
-         zy1->value(y1); 
-         snprintf(tmpbuf, sizeof(tmpbuf), fmt, iw->id.getY(y1));
-         zy1v->value(tmpbuf);
-         
-         zy2->value(y2); 
-         snprintf(tmpbuf, sizeof(tmpbuf), fmt, iw->id.getY(y2));
-         zy2v->value(tmpbuf);
-       }
-      else
-       zoom_group->deactivate();
-         
-      ox = x;
-      oy = y;
-      
-    }
-  
-  static const int event_mask=FL_CTRL|FL_SHIFT;
-  static std::map<int, string> h;
-// This is where the status bar help goes
-// Add entries as needed.
-  if(h.size() == 0)
-    {
-      h[0] = "B1: X Linecut; B2: Y Linecut; B3: Control Win";
-      h[FL_CTRL] = "B1: Arb Linecut; B2: Move Endpt; B3: Drag Linecut";
-      h[FL_SHIFT] = "B1: Drag Zoom; B3: Move Zoom Window";
-    }  
-  static int last_state = -1;
-  
-  int state = Fl::event_state() & event_mask;
-  // Horrible hack to handle XWindows shift state bug
-  if(key == FL_Shift_L || key == FL_Shift_R)
-    {
-      if(down)
-       state = state | FL_SHIFT;
-      else
-       state = state & ~FL_SHIFT;
-    }
-  if(key == FL_Control_L || key == FL_Control_R)
-    {
-      if(down)
-       state = state | FL_CTRL;
-      else
-       state = state & ~FL_CTRL;
-    }
-
-  if(last_state != state)
-    {
-      // This will automagically make an empty entry if event_state 
-      // is not in the help database  
-      const char *help = h[state].c_str(); 
-      help_bar->value(help);
-      last_state = state;
-    }
-}
-
-void reload_cb(Fl_Widget *, void *)
-{
-  dirent **dirlist;
-  int n;
-  
-  n = fl_filename_list(".", &dirlist);
-  if (replaceb->value()) clear_files();
-
-  for (int i = 0; i<n; i++)
-    if (fl_filename_match(dirlist[i]->d_name, reload_text->value()))
-      add_file(dirlist[i]->d_name);
-
-  if (filenames.size() == 0)
-    {
-      fl_alert("No files found!! Reverting to the list of files given on command line.");
-      load_orig_files();
-    }
-  
-  filech->value(0);
-  filech->do_callback();
-
-  for (int i = n; i > 0;) 
-    free((void*)(dirlist[--i]));
-  free((void*)dirlist);
-
-}
-
-
-/* 
-  =============== Serialization Code ==========================
-  boost stores class versions, not archive versions.  In order to maintain backwards compatability
-  for the "top level" objects (of which there are probably too many, because the FLTK widgets aren't
-  encapsulated in a class), we introduce a helper class here. */
-const char * spyviewSettingsDir; // Ugly ugly ugly -- this belongs in the class, but spyview_ui.C wants it as well.
-                             //  Maybe the class shouldn't be static...
-
-class Spyview_Serializer_t
-{
-public:
-  typedef boost::archive::text_iarchive input_archive;
-  typedef boost::archive::text_oarchive output_archive;
-
-// Directory setup functions.
-  std::string settingsDir;
-
-  void maybe_mkdir(const char *name)
-  {
-#ifdef WIN32
-    if(mkdir(name) == 0)
-#else
-    if(mkdir(name,0777) == 0)
-#endif
-      return;
-    
-    switch(errno)
-      {
-      case EEXIST:
-       return;
-      default:
-       warn("Unable to create directory \"%s\": %s\n",name,strerror(errno));
-       return;
-      }
-  }
-
-  void initSettingsDir() // Use the system dependent userdir
-  {
-    string buf = userdir;
-    maybe_mkdir(buf.c_str());
-    buf = buf + DIRECTORY_SEPARATOR + "settings"; // note += won't work because the cast is wrong...
-    settingsDir = buf;
-    maybe_mkdir(buf.c_str());
-    spyviewSettingsDir = settingsDir.c_str();
-  }
-
-// Save/load functions
-  void save(std::string &name)
-  {
-    initSettingsDir();
-    if(name.empty())
-      {
-      name = settingsDir + DIRECTORY_SEPARATOR + "default.svs";
-      }
-    const char *fname = name.c_str();
-    try
-      {
-       std::ofstream ofs(fname, std::ios::binary);
-       if(!ofs.good())
-         throw(1);
-       output_archive oa(ofs); //doesn't work under win32?
-       oa & (*this);
-      }
-    catch (boost::archive::archive_exception &e)
-      {
-       warn("Error saving spyview settings: %s\n",e.what());
-      }
-    catch (std::exception &e)
-      {
-       warn("Error saving settings file \"%s\": %s (%s)\n",fname,e.what(),strerror(errno));
-      }
-    catch (...)
-      {
-       error("Unknown error from settings file\n");
-      }
-  };
-
-  void load(std::string &name)
-  {
-    initSettingsDir();
-    if(name.empty())
-      {
-       
-       name = settingsDir + DIRECTORY_SEPARATOR + "default.svs";
-      }
-    
-    const char *fname = name.c_str();
-    info("loading settings from %s\n", fname);
-    try 
-      {
-       std::ifstream ifs(fname, std::ios::binary);
-       if(!ifs.good()) 
-         {
-           warn("IFS is not good!\n");
-           throw(1);
-         }
-       input_archive ia(ifs);
-       ia & (*this);
-      }
-    catch (boost::archive::archive_exception &e)
-      {
-       warn("Error loading settings %s\nTry overwriting the default settings file to get rid of this error.\n",e.what());
-      }
-    catch (std::exception &e)
-      {
-       warn("Spyview serialization error; did not load settings: %s (%s)\nTry overwriting the default settings file to get rid of this error.\n",e.what(),typeid(e).name());
-      }
-    catch (...)
-      {
-       warn("Unable to load settings file \"%s\": %s\nTry overwriting the default settings file to get rid of this error.\n",fname,strerror(errno));
-      }
-  };
-  
-  template<class Archive>
-  void serialize(Archive & ar, const unsigned int version)
-  {
-    ar & (*iw);
-
-    // Newer versions of spyview hide the extensions on the colormaps.
-    // This causes the chooser serialization to ignore extensions so old
-    // save files still work.
-    push_chooser_equality(chooser_equality_noextension);
-    ar & flcast(cmapch);
-    pop_chooser_equality();
-
-    ar & flcast(norm_on_load);
-    ar & flcast(squareb);
-    ar & flcast(dim);
-
-    if (version >= 1)
-      ar & flcast(gpwith);
-    if (version >= 2)
-      {
-       ar & iw->id.datfile_type;
-       ar & iw->id.gpload_type;
-       ar & iw->id.gp_column;
-       //ar & iw->id.mtx_cut_type; // This one is quite annoying, actually...
-      }
-    if (version >= 3)
-      {
-       ar & iw->id.mtx.parse_txt;
-       Fl_Input tmp(0,0,0,0,""); // This used to be ipc.preview_cmd
-       //ar & flcast(iw->ipc.preview_cmd);
-       ar & flcast(&tmp);
-      }
-    if (version >= 4)
-      {
-       ar & iw->id.mtx.delft_raw_units;
-      }
-    if (version >= 5)
-      {
-       ar & iw->id.mtx.delft_settings;
-      }
-    if(version == 6)
-      {
-       warn("Version 6 archives were bad..  Spypal settings ignored\n");
-      }
-    if(version >= 7)
-      {
-       ar & (*spypal);
-      }
-    if(Archive::is_loading::value)
-      {
-       wpbox->value(iw->wpercent);
-       bpbox->value(iw->bpercent);
-       cmrot->value(iw->colormap_rotation_angle);
-       cmrot_roller->value(iw->colormap_rotation_angle);
-       if (version >= 1)
-         iw->gp_with_string = gpwith->value();
-       iw->setXZoom(iw->xzoom); // make sure to call this after updating class variables as it calls update_widgets()
-       if(reinterpret_cast<int>(cmapch->mvalue()->user_data()) == -1) // Custom
-         {
-           cmap_is_ppm = false;
-           spypal->recalculate(true);
-         }
-      }
-  };
-};
-static Spyview_Serializer_t Spyview_Serializer;
-
-BOOST_CLASS_VERSION(Spyview_Serializer_t, 7); // Increment this if the archive format changes.
-
-void savesettings(std::string name)
-{
-  Spyview_Serializer.save(name);
-}
-
-void loadsettings(std::string name)
-{
-  Spyview_Serializer.load(name);
-  cmapch->do_callback();
-  filech->do_callback();
-}
-
-/* Motivation: open *always* returns the lowest numbered file descriptor.  So by mapping which ones
-   it returs, we can figure out which are in use. */
-void showUsedFiles(bool leak) // Simulate a file descriptor leak if leak is true
-{
-  std::vector<int> desc;
-  size_t ulen=80;
-  int cnt = 0;
-  int used[ulen];
-
-  while(1)
-    {
-      int f = open(filenames[0].c_str(), O_RDONLY); // A file that should be available in both windows and unix.
-      if(f < 0)
-       {
-         warn("Unable to check file descriptors!  First .pgm file \"%s\": %s\n",
-              filenames[0].c_str(), strerror(errno));
-         goto cleanup;
-       }
-      if(f > ulen)
-       {
-         close(f);
-         break;
-       }
-      else
-       desc.push_back(f);
-    }
-
-  for(int i = 0; i < ulen; i++)
-    used[i] = 1;
-  for(int i = 0; i < desc.size(); i++)
-    {
-      if(desc[i] < ulen)
-       used[desc[i]] = 0;
-    }
-  printf("Leak map: ");
-  for(int i = 0; i < ulen; i++)
-    {
-      printf("%d", used[i]);
-      if(used[i])
-       cnt++;
-    }
-  printf("\n");
-  printf("%d Total descriptors in use\n",cnt);
- cleanup:
-  while(desc.size() > leak ? 1 : 0)
-    {
-      close(desc.back());
-      desc.pop_back();
-    }
-}
-//#endif
-
-void loadColors(char *fn)
-{
-  // Automatically pick filename
-  string filename;
-  if (fn == NULL)
-    {
-      filename = iw->output_basename;
-      filename += ".colors";
-    }
-  else
-    filename = fn;
-  info("loading colors to file %s\n", filename.c_str());
-  std::ifstream ifs(filename.c_str());
-  if (!ifs.good())
-    {
-      info("Error opening colors file: %s\n", filename.c_str());
-      return;
-    } 
-  boost::archive::text_iarchive ar(ifs);
-  
-  // Version 1: stuff to archive:
-  //
-  // hmin
-  // hmax
-  // gamma
-  // gamma_center
-  // quant_min
-  // quant_max
-  // colormap
-  //
-
-  int version;
-  ar & version;
-  ar & iw->hmin;
-  ar & iw->hmax;
-  ar & iw->gam;
-  ar & iw->gcenter;
-  ar & iw->id.qmin;
-  ar & iw->id.qmax;
-  ar & flcast(cmapch);
-
-  // After loading, we will:
-  //
-  // - call update_widgets()
-  // - turn off autonormalize (spyview gui widget) 
-  // - turn off autoquantize (in ImageData)
-  // - requantize the data
-  // - set the min and max
-
-  norm_on_load->value(0);
-  iw->id.auto_quant = false;
-  iw->id.quantize();
-  cmapch->do_callback();
-  iw->adjustHistogram(); // this should remap and replot the data
-  update_widgets();
-}
-
-
-void saveColors(char *fn)
-{
-  // Automatically pick filename
-  string filename;
-  if (fn == NULL)
-    {
-      filename = iw->output_basename;
-      filename += ".colors";
-    }
-  else
-    filename = fn;
-  info("saving colors to file %s\n", filename.c_str());
-  std::ofstream ofs(filename.c_str());
-  if (!ofs.good())
-    {
-      info("Error saving to colors file: %s\n", filename.c_str());
-      return;
-    } 
-   boost::archive::text_oarchive ar(ofs);
-
-  // Note -- we need to set the version for the save direction, 
-  // otherwise it'll be random.
-  int version = 1;
-  ar & version;
-  // All this stuff is in version 1
-  ar & iw->hmin;
-  ar & iw->hmax;
-  ar & iw->gam;
-  ar & iw->gcenter;
-  ar & iw->id.qmin;
-  ar & iw->id.qmax;
-  ar & flcast(cmapch);
-}
-
-void saveImageProcessing(char *fn)
-{
-  // Automatically pick filename
-  string filename;
-  if (fn == NULL)
-    {
-      filename = iw->output_basename;
-      filename += ".img_proc";
-    }
-  else
-    filename = fn;
-  info("saving image processing to file %s\n", filename.c_str());
-  std::ofstream ofs(filename.c_str());
-  if (!ofs.good())
-    {
-      warn("Error saving to image processing file: %s\n", filename.c_str());
-      return;
-    } 
-  boost::archive::text_oarchive ar(ofs);
-
-  int tmp = pqueue->size(); 
-  ar & tmp;
-  fprintf(stderr,"Saving %d process entries\n",tmp);
-  for(int i = 1; i <= pqueue->size(); i++)
-    {            
-      std::string tmp = pqueue->text(i);
-      ar & tmp;
-      Image_Operation * t = reinterpret_cast<Image_Operation *>(pqueue->data(i));
-      ar & t;
-    }
-}
-
-void loadImageProcessing(char *fn)
-{
-  // Automatically pick filename
-  string filename;
-  if (fn == NULL)
-    {
-      filename = iw->output_basename;
-      filename += ".img_proc";
-    }
-  else
-    filename = fn;
-  info("loading image_processing from file %s\n", filename.c_str());
-  std::ifstream ifs(filename.c_str());
-  if (!ifs.good())
-    {
-      info("Error opening image processing file: %s\n", filename.c_str());
-      return;
-    } 
-  boost::archive::text_iarchive ar(ifs);
-
-  for(int i = 1 ; i <= pqueue->size(); i++)
-    delete reinterpret_cast<Image_Operation *>(pqueue->data(i));
-  int len;
-  pqueue->clear();
-  ar & len; // This has the size  of the expected queue
-  fprintf(stderr,"Loading %d process entries\n",len);
-  for(int i = 1; i <= len; i++)
-    {
-      std::string tmp;
-      ar & tmp;
-      Image_Operation *op;
-      ar & op;
-      pqueue->add(tmp.c_str(),op);
-    }
-  reload_data();
-}
-
diff --git a/spyview/static_link_notes.txt~ b/spyview/static_link_notes.txt~
deleted file mode 100644 (file)
index 0f0d35e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-otool -L 
-
-list the libraries a program is linked against
diff --git a/spyview/update_exe.sh~ b/spyview/update_exe.sh~
deleted file mode 100755 (executable)
index b481f20..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-set -x
-exe="spybrowse.exe dat2mtx.exe spyview.exe spyview_console.exe spybrowse_console.exe mtxdiff.exe huettel2mtx.exe toeno2mtx.exe *.bat help.txt"
-scp $exe kavli:public_html/spyview/windows_exe
diff --git a/spyview/update_webpage.sh~ b/spyview/update_webpage.sh~
deleted file mode 100755 (executable)
index ccca614..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-set -x
-# remote=qt.tn.tudelft.nl
-# exe="spybrowse.exe dat2mtx.exe spyview.exe spyview_console.exe spybrowse_console.exe mtxdiff.exe huettel2mtx.exe toeno2mtx.exe *.bat pgnuplot.exe wgnuplot.exe gilles2mtx.exe help.txt updates_page.url ns2pgm.exe"
-# cp $exe spyview_windows
-# scp $exe $remote:public_html/spyview/windows_exe
-# rm spyview_windows.zip
-# zip -r spyview_windows.zip spyview_windows
-# #(cd spyview_windows; zip -r ../spyview_windows.zip .)
-# scp spyview_windows.zip $remote:public_html/spyview/
-# scp spyview_console.exe help.txt $remote:public_html/spyview/
-
-# Now we're building on the local machine
-exe="spybrowse.exe dat2mtx.exe spyview.exe spyview_console.exe spybrowse_console.exe mtxdiff.exe huettel2mtx.exe toeno2mtx.exe *.bat pgnuplot.exe wgnuplot.exe gilles2mtx.exe help.txt updates_page.url ns2pgm.exe"
-cp $exe spyview_windows
-cp ~/public_html/spyview/windows_exe
-rm spyview_windows.zip
-zip -r spyview_windows.zip spyview_windows
-#(cd spyview_windows; zip -r ../spyview_windows.zip .)
-cp spyview_windows.zip ~/public_html/spyview/
-cp spyview_console.exe help.txt ~/public_html/spyview/
-date > ~/public_html/spyview/update.html