# include <dvo.h>

/* read data from raw-style catalog file; set data format values based on file */

int dvo_catalog_load_raw (Catalog *catalog, int VERBOSE) {
  
  int Nitems, nitems;
  int i, Nmeas, Nmiss, size;
  int NewMeasure, Nskip;
  int AverageSize, MeasureSize, MissingSize, SecFiltSize;
  FILE *f;
  struct stat filestatus;
  char format[80], telescope[80];
  SecFilt *primary;

  f = catalog[0].f;

  /* move pointer past header -- must be already read (load_catalog) */
  fseek (f, catalog[0].header.size, SEEK_SET);

  /* get the components from the header */
  catalog[0].Naverage = catalog[0].Nmeasure = catalog[0].Nmissing = catalog[0].Nsecfilt = 0;
  if (!gfits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &catalog[0].Naverage)) return (FALSE);
  if (!gfits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &catalog[0].Nmeasure)) return (FALSE);
  if (!gfits_scan (&catalog[0].header, "NMISS",    "%d", 1, &catalog[0].Nmissing)) return (FALSE);
  if (!gfits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &catalog[0].Nsecfilt)) catalog[0].Nsecfilt = 0;

  /* determine catalog format */
  catalog[0].catformat = DVO_FORMAT_UNDEF;
  if (gfits_scan (&catalog[0].header, "FORMAT",  "%s", 1, format)) {
    catalog[0].catformat = dvo_catalog_catformat (format);
    if (catalog[0].catformat != DVO_FORMAT_UNDEF) goto got_format;
  }
  /* special cases: old versions of the DB tables which were poorly identified */
  if (gfits_scan (&catalog[0].header, "NEWMEAS",  "%t", 1, &NewMeasure)) {
    catalog[0].catformat = DVO_FORMAT_ELIXIR; // special case for ELIXIR
    goto got_format;
  }
  if (gfits_scan (&catalog[0].header, "TELESCOP",  "%s", 1, telescope)) {
    if (!strncmp (telescope, "LONEOS", strlen("LONEOS"))) {
      catalog[0].catformat = DVO_FORMAT_LONEOS; // special case for LONEOS
      goto got_format;
    }
    if (!strncmp (telescope, "1.3m McGraw-Hill", strlen("1.3m McGraw-Hill"))) {
      catalog[0].catformat = DVO_FORMAT_ELIXIR; // special case for ELIXIR
      goto got_format;
    }
  }
  if (VERBOSE) fprintf (stderr, "cannot determine catalog format\n");
  return (FALSE);

got_format:
  /* determine datatype sizes */
  switch (catalog[0].catformat) {
    case DVO_FORMAT_INTERNAL:
      AverageSize = sizeof(Average);
      MeasureSize = sizeof(Measure);
      SecFiltSize = sizeof(SecFilt);
      break;
    case DVO_FORMAT_LONEOS:
      AverageSize = sizeof(AverageLoneos);
      MeasureSize = sizeof(MeasureLoneos);
      SecFiltSize = sizeof(SecFiltLoneos);
      break;
    case DVO_FORMAT_ELIXIR:
      AverageSize = sizeof(AverageElixir);
      MeasureSize = sizeof(MeasureElixir);
      SecFiltSize = sizeof(SecFiltElixir);
      break;
    case DVO_FORMAT_PANSTARRS_DEV_0:
      AverageSize = sizeof(AveragePanstarrs_DEV_0);
      MeasureSize = sizeof(MeasurePanstarrs_DEV_0);
      SecFiltSize = sizeof(SecFiltPanstarrs_DEV_0);
      break;
    case DVO_FORMAT_PANSTARRS_DEV_1:
      AverageSize = sizeof(AveragePanstarrs_DEV_1);
      MeasureSize = sizeof(MeasurePanstarrs_DEV_1);
      SecFiltSize = sizeof(SecFiltPanstarrs_DEV_1);
      break;
# if 0
    case DVO_FORMAT_PANSTARRS:
      AverageSize = sizeof(AveragePanstarrs);
      MeasureSize = sizeof(MeasurePanstarrs);
      SecFiltSize = sizeof(SecFiltPanstarrs);
      break;
    case DVO_FORMAT_PMTEST:
      AverageSize = sizeof(AveragePMtest);
      MeasureSize = sizeof(MeasurePanstarrs);
      SecFiltSize = sizeof(SecFiltPanstarrs);
      break;
# endif
    default:
      fprintf (stderr, "programming error in phot_catalog_raw\n");
      exit (2);
  }
  MissingSize = sizeof (Missing);

  /* predicted file size - for double checking data validity */
  size = catalog[0].header.size;
  size += AverageSize * catalog[0].Naverage;
  size += MeasureSize * catalog[0].Nmeasure;
  size += MissingSize * catalog[0].Nmissing;
  size += SecFiltSize * catalog[0].Nsecfilt * catalog[0].Naverage;

  /* check that file size makes sense */
  if (stat (catalog[0].filename, &filestatus) == -1) {
    if (VERBOSE) fprintf (stderr, "failed to get status of catalog\n");
    return (FALSE);
  }
  if (size > filestatus.st_size) {
    if (VERBOSE) {
      fprintf (stderr, "star catalog has inconsistent size\n");
      fprintf (stderr, "average: %d = %d bytes\n", catalog[0].Naverage, catalog[0].Naverage*AverageSize);
      fprintf (stderr, "measure: %d = %d bytes\n", catalog[0].Nmeasure, catalog[0].Nmeasure*MeasureSize);
      fprintf (stderr, "missing: %d = %d bytes\n", catalog[0].Nmissing, catalog[0].Nmissing*MissingSize);
      fprintf (stderr, "secfilt: %d = %d bytes\n", catalog[0].Nsecfilt, catalog[0].Nsecfilt*SecFiltSize*catalog[0].Naverage);
      fprintf (stderr, "expect: %d, found: %d\n", size, (int)filestatus.st_size);
    }
    return (FALSE);
  } 
  if (size < filestatus.st_size) {
    if (VERBOSE) fprintf (stderr, "warning: file larger than expected\n");
  } 

  if (catalog[0].Naverage == 0) {
    if (VERBOSE) fprintf (stderr, "no stars yet in catalog %s\n", catalog[0].filename);
    return (TRUE);
  }

  /* read and convert the averages (use a macro to clean this up?) */
  /* old versions of DVO stored one of the average magnitudes in Average. we save this if needed */
  if (catalog[0].catflags & LOAD_AVES) {
    catalog[0].average = ReadRawAverage (catalog[0].f, catalog[0].Naverage, catalog[0].catformat, &primary);
  } else {
    /* skip over averages */
    Nskip = catalog[0].Naverage * AverageSize;
    fseek (f, Nskip, SEEK_CUR); 
  }    
  
  /* read and convert the measures (use a macro to clean this up?) */
  if (catalog[0].catflags & LOAD_MEAS) {
    catalog[0].measure = ReadRawMeasure (catalog[0].f, catalog[0].Nmeasure, catalog[0].catformat);
  } else {
    /* skip over measures */
    Nskip = catalog[0].Nmeasure * MeasureSize;
    fseek (f, Nskip, SEEK_CUR); 
  }    

  /* read and convert missing */
  if (catalog[0].catflags & LOAD_MISS) {
    ALLOCATE (catalog[0].missing, Missing, MAX (catalog[0].Nmissing, 1));
    Nitems = catalog[0].Nmissing;
    nitems = fread (catalog[0].missing, MissingSize, Nitems, f);
    if (nitems != Nitems) {
      if (VERBOSE) fprintf (stderr, "failed to read missing from catalog file %s (%d vs %d)\n", catalog[0].filename, nitems, Nitems);
      return (FALSE);
    }
    gfits_convert_Missing (catalog[0].missing, MissingSize, Nitems);
  } else {
    /* skip over missings */
    Nskip = catalog[0].Nmissing * MissingSize;
    fseek (f, Nskip, SEEK_CUR); 
  }
  
  /* read and convert secfilt */
  if (catalog[0].catflags & LOAD_SECF) {
    Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
    catalog[0].secfilt = ReadRawSecFilt (catalog[0].f, Nitems, catalog[0].catformat);

    /* if primary is defined, we were supplied with one additional average magnitude from Average
       we need to interleave these magnitudes with the secfilt entries just loaded */
    if (primary != NULL) {
      int Ntmpfilt, Nsecfilt, Ntotal, i, j;
      SecFilt *tmpfilt;
      tmpfilt  = catalog[0].secfilt;
      Ntmpfilt = catalog[0].Nsecfilt;
      Nsecfilt = catalog[0].Nsecfilt + 1;
      Ntotal = Nsecfilt * catalog[0].Naverage;
      ALLOCATE (catalog[0].secfilt, SecFilt, Ntotal);
      for (i = 0; i < catalog[0].Naverage; i++) {
	catalog[0].secfilt[i*Nsecfilt + 0] = primary[i];
	for (j = 0; j < Ntmpfilt; j++) {
	  catalog[0].secfilt[i*Nsecfilt + j + 1] = tmpfilt[i*Ntmpfilt + j];
	}
      }		
      catalog[0].Nsecfilt = Nsecfilt;
      free (primary);
    } 

  } else {
    /* skip over secfilts */
    Nskip = catalog[0].Nsecfilt * catalog[0].Naverage * SecFiltSize;
    fseek (f, Nskip, SEEK_CUR); 
    if (primary != NULL) free (primary);
  }

  if (VERBOSE) fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing, %d secondary filters)\n", 
			catalog[0].Naverage, catalog[0].filename, catalog[0].Nmeasure, catalog[0].Nmissing, catalog[0].Nsecfilt);

  /* check data integrity */
  if (catalog[0].catflags & LOAD_AVES) {
    for (i = Nmeas = Nmiss = 0; i < catalog[0].Naverage; i++) {
      Nmeas += catalog[0].average[i].Nm; 
      Nmiss += catalog[0].average[i].Nn; 
    }
    if ((Nmeas != catalog[0].Nmeasure) || (Nmiss != catalog[0].Nmissing)) {
      if (VERBOSE) {
	fprintf (stderr, "****** data in catalog %s is corrupt, sums don't check\n", catalog[0].filename);
	fprintf (stderr, "****** Nmeas: %d, %d\n", Nmeas, catalog[0].Nmeasure);
	fprintf (stderr, "****** Nmiss: %d, %d\n", Nmiss, catalog[0].Nmissing);
      }
      return (FALSE);
    }
  }

  /* save the current number so we can do partial updates */
  catalog[0].Nave_disk  = catalog[0].Naverage;
  catalog[0].Nmeas_disk = catalog[0].Nmeasure;
  catalog[0].Nmiss_disk = catalog[0].Nmissing;

  return (TRUE);
}

int dvo_catalog_save_raw (Catalog *catalog, char VERBOSE) {

  int Nitems, nitems;
  FILE *f;
  SecFilt *primary;
  SecFilt *secfilt;
  int i, j, Nsecfilt, Nallfilt, Ntotal;

  if (catalog[0].Naverage == 0) {
    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
    return (TRUE);
  }

  /* for the appropriate types, pull out the first secfilt and pass to WriteRawAverage as primary */
  if ((catalog[0].catformat == DVO_FORMAT_ELIXIR) || // special case for ELIXIR
      (catalog[0].catformat == DVO_FORMAT_LONEOS)) { // special case for LONEOS
    Nallfilt = catalog[0].Nsecfilt;
    Nsecfilt = catalog[0].Nsecfilt - 1;
    Ntotal = Nsecfilt * catalog[0].Naverage;
    ALLOCATE (primary, SecFilt, catalog[0].Naverage);
    ALLOCATE (secfilt, SecFilt, Ntotal);

    for (i = 0; i < catalog[0].Naverage; i++) {
      primary[i] = catalog[0].secfilt[i*Nallfilt + 0];
      for (j = 0; j < Nsecfilt; j++) {
	secfilt[i*Nsecfilt + j] = catalog[0].secfilt[i*Nallfilt + j + 1];
      }
    }		
  } else {
    primary = NULL;
    secfilt = catalog[0].secfilt;
    Nsecfilt = catalog[0].Nsecfilt;
  }

  /* make sure header is consistent with data */
  gfits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
  gfits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
  gfits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
  gfits_modify (&catalog[0].header, "NSECFILT", "%d", 1, catalog[0].Nsecfilt);

  /* specify the appropriate data format */
  if (catalog[0].catformat == DVO_FORMAT_INTERNAL)  gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "INTERNAL");
  if (catalog[0].catformat == DVO_FORMAT_LONEOS)    gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "LONEOS");
  if (catalog[0].catformat == DVO_FORMAT_ELIXIR)    gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "ELIXIR");
  if (catalog[0].catformat == DVO_FORMAT_PANSTARRS_DEV_0) gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "PANSTARRS_DEV_0");
  if (catalog[0].catformat == DVO_FORMAT_PANSTARRS_DEV_1) gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "PANSTARRS_DEV_1");
  // if (catalog[0].catformat == DVO_FORMAT_PANSTARRS) gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "PANSTARRS");
  // if (catalog[0].catformat == DVO_FORMAT_PMTEST)    gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "PMTEST");

  /* rewind file pointers and truncate file */
  f = catalog[0].f;
  fseek (f, 0, SEEK_SET);
  ftruncate (fileno (catalog[0].f), 0);

  /* write header data (use gfits_write_header?) */
  nitems = fwrite (catalog[0].header.buffer, 1, catalog[0].header.size, f);
  if (nitems != catalog[0].header.size) {
    if (VERBOSE) fprintf (stderr, "failed to write header\n");
    goto failure;
  }

  /* write averages and measures */
  WriteRawAverage (f, catalog[0].average, catalog[0].Naverage, catalog[0].catformat, primary);
  WriteRawMeasure (f, catalog[0].measure, catalog[0].Nmeasure, catalog[0].catformat);

  /* write missing data */
  Nitems = catalog[0].Nmissing;
  gfits_convert_Missing (catalog[0].missing, sizeof(Missing), Nitems);
  nitems = fwrite (catalog[0].missing, sizeof(Missing), Nitems, f);
  if (nitems != Nitems) {
    if (VERBOSE) fprintf (stderr, "failed to write catalog file missing %s\n", catalog[0].filename);
    goto failure;
  }

  Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
  WriteRawSecFilt (f, catalog[0].secfilt, Nitems, catalog[0].catformat);

  /* free temp storage */
  if (primary != NULL) {
    free (primary);
    free (secfilt);
  }
  return (TRUE);

failure:
  /* free temp storage */
  if (primary != NULL) {
    free (primary);
    free (secfilt);
  }
  return (FALSE);
}

/*** 
     some warnings:
     - need to be wary of exit condition errors
***/

/** Average / Raw Table conversions **/

Average *ReadRawAverage (FILE *f, int Naverage, int format, SecFilt **primary) {

  int nitems;
  Average *average;

  /* in the Elixir and Loneos cases, we are supplied with an average magnitude in Average
     in these cases, save these values in primary; otherwise set primary to NULL */
  *primary = NULL;

  switch (format) {
    case DVO_FORMAT_INTERNAL: {
      ALLOCATE (average, Average, MAX (Naverage, 1));
      nitems = fread (average, sizeof(Average), Naverage, f);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
	return (NULL);
      }
      gfits_convert_Average (average, sizeof(Average), Naverage);
      break; }
    case DVO_FORMAT_ELIXIR: {
      AverageElixir *tmpAverage;
      ALLOCATE (tmpAverage, AverageElixir, MAX (Naverage, 1));
      nitems = fread (tmpAverage, sizeof(AverageElixir), Naverage, f);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
	return (NULL);
      }
      gfits_convert_AverageElixir (tmpAverage, sizeof(AverageElixir), Naverage);
      average = AverageElixirToInternal (tmpAverage, Naverage, primary);
      free (tmpAverage);
      break; }
    case DVO_FORMAT_LONEOS: {
      AverageLoneos *tmpAverage;
      ALLOCATE (tmpAverage, AverageLoneos, MAX (Naverage, 1));
      nitems = fread (tmpAverage, sizeof(AverageLoneos), Naverage, f);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
	return (NULL);
      }
      gfits_convert_AverageLoneos (tmpAverage, sizeof(AverageLoneos), Naverage);
      average = AverageLoneosToInternal (tmpAverage, Naverage, primary);
      free (tmpAverage);
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_0: {
      AveragePanstarrs_DEV_0 *tmpAverage;
      ALLOCATE (tmpAverage, AveragePanstarrs_DEV_0, MAX (Naverage, 1));
      nitems = fread (tmpAverage, sizeof(AveragePanstarrs_DEV_0), Naverage, f);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
	return (NULL);
      }
      gfits_convert_AveragePanstarrs_DEV_0 (tmpAverage, sizeof(AveragePanstarrs_DEV_0), Naverage);
      average = AveragePanstarrs_DEV_0_ToInternal (tmpAverage, Naverage);
      free (tmpAverage);
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_1: {
      AveragePanstarrs_DEV_1 *tmpAverage;
      ALLOCATE (tmpAverage, AveragePanstarrs_DEV_1, MAX (Naverage, 1));
      nitems = fread (tmpAverage, sizeof(AveragePanstarrs_DEV_1), Naverage, f);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
	return (NULL);
      }
      gfits_convert_AveragePanstarrs_DEV_1 (tmpAverage, sizeof(AveragePanstarrs_DEV_1), Naverage);
      average = AveragePanstarrs_DEV_1_ToInternal (tmpAverage, Naverage);
      free (tmpAverage);
      break; }
# if 0
    case DVO_FORMAT_PANSTARRS: {
      AveragePanstarrs *tmpAverage;
      ALLOCATE (tmpAverage, AveragePanstarrs, MAX (Naverage, 1));
      nitems = fread (tmpAverage, sizeof(AveragePanstarrs), Naverage, f);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
	return (NULL);
      }
      gfits_convert_AveragePanstarrs (tmpAverage, sizeof(AveragePanstarrs), Naverage);
      average = AveragePanstarrsToInternal (tmpAverage, Naverage);
      free (tmpAverage);
      break; }
    case DVO_FORMAT_PMTEST: {
      AveragePMtest *tmpAverage;
      ALLOCATE (tmpAverage, AveragePMtest, MAX (Naverage, 1));
      nitems = fread (tmpAverage, sizeof(AveragePMtest), Naverage, f);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
	return (NULL);
      }
      gfits_convert_AveragePMtest (tmpAverage, sizeof(AveragePMtest), Naverage);
      average = AveragePMtestToInternal (tmpAverage, Naverage);
      free (tmpAverage);
      break; }
# endif
    default:
      fprintf (stderr, "error reading measures\n");
      return (NULL);
  }
  return (average);
}

/* accepts and converts internal average formats and outputs 
   raw data in the specified format */
int WriteRawAverage (FILE *f, Average *average, int Naverage, int format, SecFilt *primary) {

  int nitems;

  switch (format) {
    case DVO_FORMAT_INTERNAL: {
      gfits_convert_Average (average, sizeof(Average), Naverage);
      nitems = fwrite (average, sizeof(Average), Naverage, f);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_ELIXIR: {
      AverageElixir *tmpAverage;
      tmpAverage = AverageInternalToElixir (average, Naverage, primary);
      gfits_convert_AverageElixir (tmpAverage, sizeof(AverageElixir), Naverage);
      nitems = fwrite (tmpAverage, sizeof(AverageElixir), Naverage, f);
      free (tmpAverage);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_LONEOS: {
      AverageLoneos *tmpAverage;
      tmpAverage = AverageInternalToLoneos (average, Naverage, primary);
      gfits_convert_AverageLoneos (tmpAverage, sizeof(AverageLoneos), Naverage);
      nitems = fwrite (tmpAverage, sizeof(AverageLoneos), Naverage, f);
      free (tmpAverage);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_0: {
      AveragePanstarrs_DEV_0 *tmpAverage;
      tmpAverage = AverageInternalToPanstarrs_DEV_0 (average, Naverage);
      gfits_convert_AveragePanstarrs_DEV_0 (tmpAverage, sizeof(AveragePanstarrs_DEV_0), Naverage);
      nitems = fwrite (tmpAverage, sizeof(AveragePanstarrs_DEV_0), Naverage, f);
      free (tmpAverage);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_1: {
      AveragePanstarrs_DEV_1 *tmpAverage;
      tmpAverage = AverageInternalToPanstarrs_DEV_1 (average, Naverage);
      gfits_convert_AveragePanstarrs_DEV_1 (tmpAverage, sizeof(AveragePanstarrs_DEV_1), Naverage);
      nitems = fwrite (tmpAverage, sizeof(AveragePanstarrs_DEV_1), Naverage, f);
      free (tmpAverage);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
	return (FALSE);
      }
      break; }
# if 0
    case DVO_FORMAT_PANSTARRS: {
      AveragePanstarrs *tmpAverage;
      tmpAverage = AverageInternalToPanstarrs (average, Naverage);
      gfits_convert_AveragePanstarrs (tmpAverage, sizeof(AveragePanstarrs), Naverage);
      nitems = fwrite (tmpAverage, sizeof(AveragePanstarrs), Naverage, f);
      free (tmpAverage);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_PMTEST: {
      AveragePMtest *tmpAverage;
      tmpAverage = AverageInternalToPMtest (average, Naverage);
      gfits_convert_AveragePMtest (tmpAverage, sizeof(AveragePMtest), Naverage);
      nitems = fwrite (tmpAverage, sizeof(AveragePMtest), Naverage, f);
      free (tmpAverage);
      if (nitems != Naverage) {
	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
	return (FALSE);
      }
      break; }
# endif
    default:
      fprintf (stderr, "error writing averages\n");
      return (FALSE);
  }
  return (TRUE);
}

/** Average / Raw Table conversions **/

Measure *ReadRawMeasure (FILE *f, int Nmeasure, int format) {

  int nitems;
  Measure *measure;

  switch (format) {
    case DVO_FORMAT_INTERNAL: {
      ALLOCATE (measure, Measure, MAX (Nmeasure, 1));
      nitems = fread (measure, sizeof(Measure), Nmeasure, f);
      if (nitems != Nmeasure) {
	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
	return (NULL);
      }
      gfits_convert_Measure (measure, sizeof(Measure), Nmeasure);
      break; }
    case DVO_FORMAT_ELIXIR: {
      MeasureElixir *tmpMeasure;
      ALLOCATE (tmpMeasure, MeasureElixir, MAX (Nmeasure, 1));
      nitems = fread (tmpMeasure, sizeof(MeasureElixir), Nmeasure, f);
      if (nitems != Nmeasure) {
	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
	return (NULL);
      }
      gfits_convert_MeasureElixir (tmpMeasure, sizeof(MeasureElixir), Nmeasure);
      measure = MeasureElixirToInternal (tmpMeasure, Nmeasure);
      free (tmpMeasure);
      break; }
    case DVO_FORMAT_LONEOS: {
      MeasureLoneos *tmpMeasure;
      ALLOCATE (tmpMeasure, MeasureLoneos, MAX (Nmeasure, 1));
      nitems = fread (tmpMeasure, sizeof(MeasureLoneos), Nmeasure, f);
      if (nitems != Nmeasure) {
	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
	return (NULL);
      }
      gfits_convert_MeasureLoneos (tmpMeasure, sizeof(MeasureLoneos), Nmeasure);
      measure = MeasureLoneosToInternal (tmpMeasure, Nmeasure);
      free (tmpMeasure);
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_0: {
      MeasurePanstarrs_DEV_0 *tmpMeasure;
      ALLOCATE (tmpMeasure, MeasurePanstarrs_DEV_0, MAX (Nmeasure, 1));
      nitems = fread (tmpMeasure, sizeof(MeasurePanstarrs_DEV_0), Nmeasure, f);
      if (nitems != Nmeasure) {
	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
	return (NULL);
      }
      gfits_convert_MeasurePanstarrs_DEV_0 (tmpMeasure, sizeof(MeasurePanstarrs_DEV_0), Nmeasure);
      measure = MeasurePanstarrs_DEV_0_ToInternal (tmpMeasure, Nmeasure);
      free (tmpMeasure);
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_1: {
      MeasurePanstarrs_DEV_1 *tmpMeasure;
      ALLOCATE (tmpMeasure, MeasurePanstarrs_DEV_1, MAX (Nmeasure, 1));
      nitems = fread (tmpMeasure, sizeof(MeasurePanstarrs_DEV_1), Nmeasure, f);
      if (nitems != Nmeasure) {
	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
	return (NULL);
      }
      gfits_convert_MeasurePanstarrs_DEV_1 (tmpMeasure, sizeof(MeasurePanstarrs_DEV_1), Nmeasure);
      measure = MeasurePanstarrs_DEV_1_ToInternal (tmpMeasure, Nmeasure);
      free (tmpMeasure);
      break; }
# if 0
    case DVO_FORMAT_PANSTARRS: {
      MeasurePanstarrs *tmpMeasure;
      ALLOCATE (tmpMeasure, MeasurePanstarrs, MAX (Nmeasure, 1));
      nitems = fread (tmpMeasure, sizeof(MeasurePanstarrs), Nmeasure, f);
      if (nitems != Nmeasure) {
	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
	return (NULL);
      }
      gfits_convert_MeasurePanstarrs (tmpMeasure, sizeof(MeasurePanstarrs), Nmeasure);
      measure = MeasurePanstarrsToInternal (tmpMeasure, Nmeasure);
      free (tmpMeasure);
      break; }
# endif
    default:
      fprintf (stderr, "error reading measures\n");
      return (NULL);
  }
  return (measure);
}

/* accepts and converts internal measure formats and outputs 
   raw data in the specified format */
int WriteRawMeasure (FILE *f, Measure *measure, int Nmeasure, int format) {

  int nitems;

  switch (format) {
    case DVO_FORMAT_INTERNAL: {
      gfits_convert_Measure (measure, sizeof(Measure), Nmeasure);
      nitems = fwrite (measure, sizeof(Measure), Nmeasure, f);
      if (nitems != Nmeasure) {
	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_ELIXIR: {
      MeasureElixir *tmpMeasure;
      tmpMeasure = MeasureInternalToElixir (measure, Nmeasure);
      gfits_convert_MeasureElixir (tmpMeasure, sizeof(MeasureElixir), Nmeasure);
      nitems = fwrite (tmpMeasure, sizeof(MeasureElixir), Nmeasure, f);
      free (tmpMeasure);
      if (nitems != Nmeasure) {
	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_LONEOS: {
      MeasureLoneos *tmpMeasure;
      tmpMeasure = MeasureInternalToLoneos (measure, Nmeasure);
      gfits_convert_MeasureLoneos (tmpMeasure, sizeof(MeasureLoneos), Nmeasure);
      nitems = fwrite (tmpMeasure, sizeof(MeasureLoneos), Nmeasure, f);
      free (tmpMeasure);
      if (nitems != Nmeasure) {
	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_0: {
      MeasurePanstarrs_DEV_0 *tmpMeasure;
      tmpMeasure = MeasureInternalToPanstarrs_DEV_0 (measure, Nmeasure);
      gfits_convert_MeasurePanstarrs_DEV_0 (tmpMeasure, sizeof(MeasurePanstarrs_DEV_0), Nmeasure);
      nitems = fwrite (tmpMeasure, sizeof(MeasurePanstarrs_DEV_0), Nmeasure, f);
      free (tmpMeasure);
      if (nitems != Nmeasure) {
	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_1: {
      MeasurePanstarrs_DEV_1 *tmpMeasure;
      tmpMeasure = MeasureInternalToPanstarrs_DEV_1 (measure, Nmeasure);
      gfits_convert_MeasurePanstarrs_DEV_1 (tmpMeasure, sizeof(MeasurePanstarrs_DEV_1), Nmeasure);
      nitems = fwrite (tmpMeasure, sizeof(MeasurePanstarrs_DEV_1), Nmeasure, f);
      free (tmpMeasure);
      if (nitems != Nmeasure) {
	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
	return (FALSE);
      }
      break; }
# if 0
    case DVO_FORMAT_PANSTARRS: {
      MeasurePanstarrs *tmpMeasure;
      tmpMeasure = MeasureInternalToPanstarrs (measure, Nmeasure);
      gfits_convert_MeasurePanstarrs (tmpMeasure, sizeof(MeasurePanstarrs), Nmeasure);
      nitems = fwrite (tmpMeasure, sizeof(MeasurePanstarrs), Nmeasure, f);
      free (tmpMeasure);
      if (nitems != Nmeasure) {
	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
	return (FALSE);
      }
      break; }
# endif
    default:
      fprintf (stderr, "error writing measures\n");
      return (FALSE);
  }
  return (TRUE);
}

/** SecFilt / Raw Table conversions **/

SecFilt *ReadRawSecFilt (FILE *f, int Nsecfilt, int format) {

  int nitems;
  SecFilt *secfilt;

  switch (format) {
    case DVO_FORMAT_INTERNAL: {
      ALLOCATE (secfilt, SecFilt, MAX (Nsecfilt, 1));
      nitems = fread (secfilt, sizeof(SecFilt), Nsecfilt, f);
      if (nitems != Nsecfilt) {
	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
	return (NULL);
      }
      gfits_convert_SecFilt (secfilt, sizeof(SecFilt), Nsecfilt);
      break; }
    case DVO_FORMAT_ELIXIR: {
      SecFiltElixir *tmpSecFilt;
      ALLOCATE (tmpSecFilt, SecFiltElixir, MAX (Nsecfilt, 1));
      nitems = fread (tmpSecFilt, sizeof(SecFiltElixir), Nsecfilt, f);
      if (nitems != Nsecfilt) {
	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
	return (NULL);
      }
      gfits_convert_SecFiltElixir (tmpSecFilt, sizeof(SecFiltElixir), Nsecfilt);
      secfilt = SecFiltElixirToInternal (tmpSecFilt, Nsecfilt);
      free (tmpSecFilt);
      break; }
    case DVO_FORMAT_LONEOS: {
      SecFiltLoneos *tmpSecFilt;
      ALLOCATE (tmpSecFilt, SecFiltLoneos, MAX (Nsecfilt, 1));
      nitems = fread (tmpSecFilt, sizeof(SecFiltLoneos), Nsecfilt, f);
      if (nitems != Nsecfilt) {
	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
	return (NULL);
      }
      gfits_convert_SecFiltLoneos (tmpSecFilt, sizeof(SecFiltLoneos), Nsecfilt);
      secfilt = SecFiltLoneosToInternal (tmpSecFilt, Nsecfilt);
      free (tmpSecFilt);
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_0: {
      SecFiltPanstarrs_DEV_0 *tmpSecFilt;
      ALLOCATE (tmpSecFilt, SecFiltPanstarrs_DEV_0, MAX (Nsecfilt, 1));
      nitems = fread (tmpSecFilt, sizeof(SecFiltPanstarrs_DEV_0), Nsecfilt, f);
      if (nitems != Nsecfilt) {
	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
	return (NULL);
      }
      gfits_convert_SecFiltPanstarrs_DEV_0 (tmpSecFilt, sizeof(SecFiltPanstarrs_DEV_0), Nsecfilt);
      secfilt = SecFiltPanstarrs_DEV_0_ToInternal (tmpSecFilt, Nsecfilt);
      free (tmpSecFilt);
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_1: {
      SecFiltPanstarrs_DEV_1 *tmpSecFilt;
      ALLOCATE (tmpSecFilt, SecFiltPanstarrs_DEV_1, MAX (Nsecfilt, 1));
      nitems = fread (tmpSecFilt, sizeof(SecFiltPanstarrs_DEV_1), Nsecfilt, f);
      if (nitems != Nsecfilt) {
	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
	return (NULL);
      }
      gfits_convert_SecFiltPanstarrs_DEV_1 (tmpSecFilt, sizeof(SecFiltPanstarrs_DEV_1), Nsecfilt);
      secfilt = SecFiltPanstarrs_DEV_1_ToInternal (tmpSecFilt, Nsecfilt);
      free (tmpSecFilt);
      break; }
# if 0
    case DVO_FORMAT_PANSTARRS: {
      SecFiltPanstarrs *tmpSecFilt;
      ALLOCATE (tmpSecFilt, SecFiltPanstarrs, MAX (Nsecfilt, 1));
      nitems = fread (tmpSecFilt, sizeof(SecFiltPanstarrs), Nsecfilt, f);
      if (nitems != Nsecfilt) {
	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
	return (NULL);
      }
      gfits_convert_SecFiltPanstarrs (tmpSecFilt, sizeof(SecFiltPanstarrs), Nsecfilt);
      secfilt = SecFiltPanstarrsToInternal (tmpSecFilt, Nsecfilt);
      free (tmpSecFilt);
      break; }
# endif
    default:
      fprintf (stderr, "error reading measures\n");
      return (NULL);
  }
  return (secfilt);
}

/* accepts and converts internal secfilt formats and outputs 
   raw data in the specified format */
int WriteRawSecFilt (FILE *f, SecFilt *secfilt, int Nsecfilt, int format) {

  int nitems;

  switch (format) {
    case DVO_FORMAT_INTERNAL: {
      gfits_convert_SecFilt (secfilt, sizeof(SecFilt), Nsecfilt);
      nitems = fwrite (secfilt, sizeof(SecFilt), Nsecfilt, f);
      if (nitems != Nsecfilt) {
	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_ELIXIR: {
      SecFiltElixir *tmpSecFilt;
      tmpSecFilt = SecFiltInternalToElixir (secfilt, Nsecfilt);
      gfits_convert_SecFiltElixir (tmpSecFilt, sizeof(SecFiltElixir), Nsecfilt);
      nitems = fwrite (tmpSecFilt, sizeof(SecFiltElixir), Nsecfilt, f);
      free (tmpSecFilt);
      if (nitems != Nsecfilt) {
	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_LONEOS: {
      SecFiltLoneos *tmpSecFilt;
      tmpSecFilt = SecFiltInternalToLoneos (secfilt, Nsecfilt);
      gfits_convert_SecFiltLoneos (tmpSecFilt, sizeof(SecFiltLoneos), Nsecfilt);
      nitems = fwrite (tmpSecFilt, sizeof(SecFiltLoneos), Nsecfilt, f);
      free (tmpSecFilt);
      if (nitems != Nsecfilt) {
	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_0: {
      SecFiltPanstarrs_DEV_0 *tmpSecFilt;
      tmpSecFilt = SecFiltInternalToPanstarrs_DEV_0 (secfilt, Nsecfilt);
      gfits_convert_SecFiltPanstarrs_DEV_0 (tmpSecFilt, sizeof(SecFiltPanstarrs_DEV_0), Nsecfilt);
      nitems = fwrite (tmpSecFilt, sizeof(SecFiltPanstarrs_DEV_0), Nsecfilt, f);
      free (tmpSecFilt);
      if (nitems != Nsecfilt) {
	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
	return (FALSE);
      }
      break; }
    case DVO_FORMAT_PANSTARRS_DEV_1: {
      SecFiltPanstarrs_DEV_1 *tmpSecFilt;
      tmpSecFilt = SecFiltInternalToPanstarrs_DEV_1 (secfilt, Nsecfilt);
      gfits_convert_SecFiltPanstarrs_DEV_1 (tmpSecFilt, sizeof(SecFiltPanstarrs_DEV_1), Nsecfilt);
      nitems = fwrite (tmpSecFilt, sizeof(SecFiltPanstarrs_DEV_1), Nsecfilt, f);
      free (tmpSecFilt);
      if (nitems != Nsecfilt) {
	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
	return (FALSE);
      }
      break; }
# if 0
    case DVO_FORMAT_PANSTARRS: {
      SecFiltPanstarrs *tmpSecFilt;
      tmpSecFilt = SecFiltInternalToPanstarrs (secfilt, Nsecfilt);
      gfits_convert_SecFiltPanstarrs (tmpSecFilt, sizeof(SecFiltPanstarrs), Nsecfilt);
      nitems = fwrite (tmpSecFilt, sizeof(SecFiltPanstarrs), Nsecfilt, f);
      free (tmpSecFilt);
      if (nitems != Nsecfilt) {
	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
	return (FALSE);
      }
      break; }
# endif
    default:
      fprintf (stderr, "error writing secfilts\n");
      return (FALSE);
  }
  return (TRUE);
}

