Beispiel #1
0
void addFITSKeywords(fitsfile *fptr)
{
  int status=0;

  /* TODO add other data later */
  fits_write_date(fptr, &status);
}
Beispiel #2
0
int CDfits_open_file( char *filename )
{
  int status;
  int bitpix   =  8;
  int naxis   =  0;
  long *naxes;
  
  status = 0;
  /* Open file */
  fits_create_file( &cfitsptr, filename, &status );
  /* Write primary header */
  bitpix = 8;
  naxis = 0;
  fits_create_img( cfitsptr, bitpix, naxis, naxes, &status );

  /* Add first keywords */
  fits_update_key( cfitsptr, TSTRING, "HDRVER", "1.19", "Header version", &status);
  fits_write_date( cfitsptr, &status);

  new_file = 1;
  
  
  return( status );
  
}
Beispiel #3
0
int fits_close(fitsfile *fptr, int *status) {

  int iomode;
  fits_file_mode(fptr, &iomode, status);
  if (iomode == READWRITE) {
    fits_write_date(fptr, status);
  }

  fits_close_file(fptr, status);
  fits_print_error(*status);

  return *status;
}
Beispiel #4
0
fitsfile* create_fits_file(const char* filename, int precision,
        int width, int height, int num_times, int num_channels,
        double centre_deg[2], double fov_deg[2], double start_time_mjd,
        double delta_time_sec, double start_freq_hz, double delta_freq_hz,
        int* status)
{
    long naxes[4];
    double delta;
    fitsfile* f = 0;
    FILE* t = 0;
    if (*status) return 0;

    /* Create a new FITS file and write the image headers. */
    t = fopen(filename, "rb");
    if (t)
    {
        fclose(t);
        remove(filename);
    }
    naxes[0]  = width;
    naxes[1]  = height;
    naxes[2]  = num_channels;
    naxes[3]  = num_times;
    fits_create_file(&f, filename, status);
    fits_create_img(f, (precision == OSKAR_DOUBLE ? DOUBLE_IMG : FLOAT_IMG),
            4, naxes, status);
    fits_write_date(f, status);

    /* Write axis headers. */
    delta = oskar_convert_fov_to_cellsize(fov_deg[0] * M_PI/180, width) * 180/M_PI;
    write_axis_header(f, 1, "RA---SIN", "Right Ascension",
            centre_deg[0], -delta, width / 2 + 1, 0.0, status);
    delta = oskar_convert_fov_to_cellsize(fov_deg[1] * M_PI/180, height) * 180/M_PI;
    write_axis_header(f, 2, "DEC--SIN", "Declination",
            centre_deg[1], delta, height / 2 + 1, 0.0, status);
    write_axis_header(f, 3, "FREQ", "Frequency",
            start_freq_hz, delta_freq_hz, 1.0, 0.0, status);
    write_axis_header(f, 4, "UTC", "Time",
            start_time_mjd, delta_time_sec, 1.0, 0.0, status);

    /* Write other headers. */
    fits_write_key_str(f, "BUNIT", "JY/BEAM", "Brightness units", status);
    fits_write_key_str(f, "TIMESYS", "UTC", NULL, status);
    fits_write_key_str(f, "TIMEUNIT", "s", "Time axis units", status);
    fits_write_key_dbl(f, "MJD-OBS", start_time_mjd, 10, "Start time", status);
    fits_write_key_dbl(f, "OBSRA", centre_deg[0], 10, "RA", status);
    fits_write_key_dbl(f, "OBSDEC", centre_deg[1], 10, "DEC", status);
    /*fits_flush_file(f, status);*/

    return f;
}
Beispiel #5
0
/**************************************************************************************
** INDI is asking us to add any FITS keywords to the FITS header
***************************************************************************************/
void INovaCCD::addFITSKeywords(fitsfile *fptr, INDI::CCDChip *targetChip)
{
    // Let's first add parent keywords
    INDI::CCD::addFITSKeywords(fptr, targetChip);

    // Add temperature to FITS header
    int status = 0;
    double gain =  CameraPropertiesN[CCD_GAIN_N].value;
    double blkLvl = CameraPropertiesN[CCD_BLACKLEVEL_N].value;
    fits_update_key_s(fptr, TDOUBLE, "GAIN", &gain, "CCD Gain", &status);
    fits_update_key_s(fptr, TDOUBLE, "BLACKLEVEL", &blkLvl, "CCD Black Level", &status);
    fits_write_date(fptr, &status);

}
Beispiel #6
0
void write_fits(fitsfile* fptr, int datatype, size_t width, size_t height,
                size_t num, void** images, const char* names[], int* status)
{
    // total number of pixels
    long npix = width*height;
    
    // dimensions
    int naxis = 2;
    long naxes[2] = { width, height };
    
    // writing offset
    long fpixel[2] = { 1, 1 };
    
    // write primary HDU
    fits_create_img(fptr, SHORT_IMG, 0, NULL, status);
    
    // record file origin
    fits_write_key(fptr, TSTRING, "ORIGIN", "Lensed " LENSED_VERSION, "FITS file originator", status);
    fits_write_comment(fptr, "for more information, see http://glenco.github.io/lensed/", status);
    
    // record the date of FITS creation
    fits_write_date(fptr, status);
    
    // write images
    for(size_t n = 0; n < num; ++n)
    {
        // create image extension
        fits_create_img(fptr, FLOAT_IMG, naxis, naxes, status);
        
        // write pixels
        fits_write_pix(fptr, datatype, fpixel, npix, images[n], status);
        
        // give extension name
        if(names && names[n])
            fits_write_key(fptr, TSTRING, "EXTNAME", (void*)names[n], "extension name", status);
    }
}
static fitsfile* create_fits_file(const char* filename, int precision,
        int width, int height, int num_times, int num_channels,
        double centre_deg[2], double fov_deg[2], double start_time_mjd,
        double delta_time_sec, double start_freq_hz, double delta_freq_hz,
        int horizon_mode, const char* settings_log, size_t settings_log_length,
        int* status)
{
    int imagetype;
    long naxes[4], naxes_dummy[4] = {1l, 1l, 1l, 1l};
    double delta;
    const double deg2rad = M_PI / 180.0;
    const double rad2deg = 180.0 / M_PI;
    fitsfile* f = 0;
    const char* line;
    size_t length;
    if (*status) return 0;

    /* Create a new FITS file and write the image headers. */
    if (oskar_file_exists(filename)) remove(filename);
    imagetype = (precision == OSKAR_DOUBLE ? DOUBLE_IMG : FLOAT_IMG);
    naxes[0]  = width;
    naxes[1]  = height;
    naxes[2]  = num_channels;
    naxes[3]  = num_times;
    fits_create_file(&f, filename, status);
    fits_create_img(f, imagetype, 4, naxes_dummy, status);
    fits_write_date(f, status);
    fits_write_key_str(f, "TELESCOP", "OSKAR " OSKAR_VERSION_STR, 0, status);

    /* Write axis headers. */
    if (horizon_mode)
    {
        delta = oskar_convert_fov_to_cellsize(M_PI, width);
        write_axis(f, 1, "-----SIN", "Azimuthal angle",
                0.0, -delta * rad2deg, (width + 1) / 2.0, status);
        delta = oskar_convert_fov_to_cellsize(M_PI, height);
        write_axis(f, 2, "-----SIN", "Elevation",
                90.0, delta * rad2deg, (height + 1) / 2.0, status);
    }
    else
    {
        delta = oskar_convert_fov_to_cellsize(fov_deg[0] * deg2rad, width);
        write_axis(f, 1, "RA---SIN", "Right Ascension",
                centre_deg[0], -delta * rad2deg, (width + 1) / 2.0, status);
        delta = oskar_convert_fov_to_cellsize(fov_deg[1] * deg2rad, height);
        write_axis(f, 2, "DEC--SIN", "Declination",
                centre_deg[1], delta * rad2deg, (height + 1) / 2.0, status);
    }
    write_axis(f, 3, "FREQ", "Frequency",
            start_freq_hz, delta_freq_hz, 1.0, status);
    write_axis(f, 4, "UTC", "Time",
            start_time_mjd * 86400.0, delta_time_sec, 1.0, status);

    /* Write other headers. */
    fits_write_key_str(f, "TIMESYS", "UTC", NULL, status);
    fits_write_key_str(f, "TIMEUNIT", "s", "Time axis units", status);
    fits_write_key_dbl(f, "MJD-OBS", start_time_mjd, 10, "Start time", status);
    if (!horizon_mode)
    {
        fits_write_key_dbl(f, "OBSRA", centre_deg[0], 10, "RA", status);
        fits_write_key_dbl(f, "OBSDEC", centre_deg[1], 10, "DEC", status);
    }

    /* Write the settings log up to this point as HISTORY comments. */
    line = settings_log;
    length = settings_log_length;
    for (; settings_log_length > 0;)
    {
        const char* eol;
        fits_write_history(f, line, status);
        eol = (const char*) memchr(line, '\0', length);
        if (!eol) break;
        eol += 1;
        length -= (eol - line);
        line = eol;
    }

    /* Update header keywords with the correct axis lengths.
     * Needs to be done here because CFITSIO doesn't let us write only the
     * file header with the correct axis lengths to start with. This trick
     * allows us to create a small dummy image block to write only the headers,
     * and not waste effort moving a huge block of zeros within the file. */
    fits_update_key_lng(f, "NAXIS1", naxes[0], 0, status);
    fits_update_key_lng(f, "NAXIS2", naxes[1], 0, status);
    fits_update_key_lng(f, "NAXIS3", naxes[2], 0, status);
    fits_update_key_lng(f, "NAXIS4", naxes[3], 0, status);

    return f;
}
void write_fits(char *filename, int w, int h, unsigned short *data, 
	double obs_duration, 
	char*  obs_type, 
	double obs_temperature,
    int    obs_filterNumber,
    char*  serial_number,
    char*  name,
    char*  ra,
    char*  dec,
    char*  alt,
    char * az
    )
{
    fitsfile *fptr;       /* pointer to the FITS file, defined in fitsio.h */
    int status;
    long  fpixel, nelements;

    /* Initialize FITS image parameters */

    int bitpix   =  USHORT_IMG;       /* 16-bit unsigned short pixel values */
    long naxis    =   2;              /* 2-dimensional image                */    
    long naxes[2] = { 256,256 };      /* default image 256 wide by 256 rows */

    /* Set the actual width and height of the image */

    naxes[0] = w;
    naxes[1] = h;

    /* Delete old FITS file if it already exists */  

    remove(filename); 

    /* Must initialize status before calling fitsio routines */           

    status = 0;  

    /* Create a new FITS file and show error message if one occurs */

    if (fits_create_file(&fptr, filename, &status)) 
	show_cfitsio_error( status );           

    /* Write the required keywords for the primary array image.       */
    /* Since bitpix = USHORT_IMG, this will cause cfitsio to create   */
    /* a FITS image with BITPIX = 16 (signed short integers) with     */
    /* BSCALE = 1.0 and BZERO = 32768.  This is the convention that   */
    /* FITS uses to store unsigned integers.  Note that the BSCALE    */
    /* and BZERO keywords will be automatically written by cfitsio    */
    /* in this case.                                                */

    if ( fits_create_img(fptr,  bitpix, naxis, naxes, &status) )
	show_cfitsio_error( status );          

    fpixel = 1;                               /* first pixel to write      */
    nelements = naxes[0] * naxes[1];          /* number of pixels to write */

    /* Write the array of unsigned integers to the FITS file */

    if ( fits_write_img(fptr, TUSHORT, fpixel, nelements, data, &status) )
	show_cfitsio_error( status );

    /* Write optional keywords to the header */

    if ( fits_update_key_dbl(fptr, "EXPTIME", obs_duration, -3,
		"exposure time (seconds)", &status) )
	show_cfitsio_error( status );

    if ( fits_update_key_dbl(fptr, "TEMPERAT", obs_temperature, -3,
		"temperature (C)", &status) )
	show_cfitsio_error( status );

    if ( fits_update_key_str(fptr, "IMAGETYP", 
		obs_type, "image type", &status) )
	show_cfitsio_error( status );       

    if ( fits_update_key(fptr, TSHORT, "FILTNUM", &obs_filterNumber, NULL, &status))
        show_cfitsio_error( status );       

    if ( fits_write_date(fptr, &status) )
	show_cfitsio_error( status );       

    if ( fits_update_key_str(fptr, "SERIALNO", 
		serial_number, "serial number", &status) )
	show_cfitsio_error( status ); 

    if ( fits_update_key_str(fptr, "TARGET", 
		name, "target name", &status) )
	show_cfitsio_error( status );  

    if ( fits_update_key_str(fptr, "RA", 
		ra, "right ascension", &status) )
	show_cfitsio_error( status );  

    if ( fits_update_key_str(fptr, "DEC", 
		dec, "declination", &status) )
	show_cfitsio_error( status );  

    if ( fits_update_key_str(fptr, "EPOCH", 
		"JNOW", "epoch of coordinates", &status) )
	show_cfitsio_error( status );  

    if ( fits_update_key_str(fptr, "OBJCTRA", 
		ra, "right ascension", &status) )
	show_cfitsio_error( status );  

    if ( fits_update_key_str(fptr, "OBJCTDEC", 
		dec, "declination", &status) )
	show_cfitsio_error( status );  

    if ( fits_update_key_dbl(fptr, "ALTITUDE", atof(alt), -4,
		"Altitude (deg)", &status) )
	show_cfitsio_error( status );

    if ( fits_update_key_dbl(fptr, "AZIMUTH", atof(az), -4,
		"Azimuth (deg)", &status) )
	show_cfitsio_error( status );

    /* Close the file */             

    if ( fits_close_file(fptr, &status) )              
	show_cfitsio_error( status );           

    return;
}
Beispiel #9
0
int HPXhdr(fitsfile *fptr, struct healpix *hpxdat)

{
  char   comment[64], cval[16], *ctype1, *ctype2, *descr1, *descr2, *pcode;
  int    status;
  float  cos45, crpix1, crpix2, crval1, crval2, lonpole;
  double cdelt1, cdelt2;

  status = 0;

  fits_update_key_log(fptr, "EXTEND", 0,
    "No FITS extensions are present", &status);
  fits_write_date(fptr, &status);

  /* Set pixel transformation parameters. */
  if (hpxdat->layout == 0) {
    crpix1 = (5 * hpxdat->nside + 1) / 2.0f;
  } else {
    crpix1 = (4 * hpxdat->nside + 1) / 2.0f;
  }
  crpix2 = crpix1;

  fits_write_key(fptr, TFLOAT, "CRPIX1", &crpix1,
    "Coordinate reference pixel", &status);
  fits_write_key(fptr, TFLOAT, "CRPIX2", &crpix2,
    "Coordinate reference pixel", &status);

  cos45 = (float)sqrt(2.0) / 2.0f;
  if (hpxdat->layout == 0) {
    fits_write_key_flt(fptr, "PC1_1",  cos45, -8,
      "Transformation matrix element", &status);
    fits_write_key_flt(fptr, "PC1_2",  cos45, -8,
      "Transformation matrix element", &status);
    fits_write_key_flt(fptr, "PC2_1", -cos45, -8,
      "Transformation matrix element", &status);
    fits_write_key_flt(fptr, "PC2_2",  cos45, -8,
      "Transformation matrix element", &status);
  }

  cdelt1 = -90.0 / hpxdat->nside / sqrt(2.0);
  cdelt2 = -cdelt1;
  fits_write_key_dbl(fptr, "CDELT1", cdelt1, -8,
    "[deg] Coordinate increment", &status);
  fits_write_key_dbl(fptr, "CDELT2", cdelt2, -8,
    "[deg] Coordinate increment", &status);


  /* Celestial transformation parameters. */
  if (hpxdat->layout == 0) {
    pcode = "HPX";
  } else {
    pcode = "XPH";
  }

  if (hpxdat->crdsys == 'G') {
    /* Galactic. */
    ctype1 = "GLON";
    ctype2 = "GLAT";
    descr1 = "Galactic longitude";
    descr2 = "Galactic  latitude";
  } else if (hpxdat->crdsys == 'E') {
    /* Ecliptic, who-knows-what. */
    ctype1 = "ELON";
    ctype2 = "ELAT";
    descr1 = "Ecliptic longitude";
    descr2 = "Ecliptic  latitude";
  } else if (hpxdat->crdsys == 'Q') {
    /* Equatorial, who-knows-what. */
    ctype1 = "RA--";
    ctype2 = "DEC-";
    descr1 = "Right ascension";
    descr2 = "Declination";
  } else {
    /* Unknown. */
    ctype1 = "XLON";
    ctype2 = "XLAT";
    descr1 = "Longitude";
    descr2 = " Latitude";
  }

  sprintf(cval, "%s-%s", ctype1, pcode);
  sprintf(comment, "%s in an %s projection", descr1, pcode);
  fits_write_key_str(fptr, "CTYPE1", cval, comment, &status);
  sprintf(cval, "%s-%s", ctype2, pcode);
  sprintf(comment, "%s in an %s projection", descr2, pcode);
  fits_write_key_str(fptr, "CTYPE2", cval, comment, &status);


  crval1 = 0.0f + 90.0f * hpxdat->quad;
  if (hpxdat->layout == 0) {
    crval2 =   0.0f;
  } else if (hpxdat->layout == 1) {
    crval1 += 180.0f;
    crval2  =  90.0f;
  } else {
    crval1 += 180.0f;
    crval2  = -90.0f;
  }
  if (360.0f < crval1) crval1 -= 360.0f;

  sprintf(comment, "[deg] %s at the reference point", descr1);
  fits_write_key(fptr, TFLOAT, "CRVAL1", &crval1, comment, &status);
  sprintf(comment, "[deg] %s at the reference point", descr2);
  fits_write_key(fptr, TFLOAT, "CRVAL2", &crval2, comment, &status);

  if (hpxdat->layout) {
    lonpole = 180.0f;
    sprintf(comment, "[deg] Native longitude of the celestial pole");
    fits_write_key(fptr, TFLOAT, "LONPOLE", &lonpole, comment, &status);
  }

  if (hpxdat->layout == 0) {
    fits_write_key_lng(fptr, "PV2_1", (LONGLONG)4,
      "HPX H parameter (longitude)", &status);
    fits_write_key_lng(fptr, "PV2_2", (LONGLONG)3,
      "HPX K parameter  (latitude)", &status);
  }

  /* Commentary. */
  fits_write_record(fptr, " ", &status);
  if (hpxdat->layout == 0) {
    fits_write_comment(fptr,
      "Celestial map with FITS-standard HPX coordinate system generated by",
      &status);
  } else {
    fits_write_comment(fptr,
      "Celestial map with XPH coordinate system (polar HPX) generated by",
      &status);
  }

  fits_write_comment(fptr,
    "'HPXcvt' which reorganises HEALPix data without interpolation as",
    &status);
  fits_write_comment(fptr,
    "described in \"Mapping on the HEALPix grid\" by Mark Calabretta and",
    &status);
  fits_write_comment(fptr,
    "Boud Roukema.  See http://www.atnf.csiro.au/people/Mark.Calabretta",
    &status);

  return status;
}
Beispiel #10
0
int FITSImage::saveFITS( const QString &newFilename )
{
    int status=0;
    long fpixel[2], nelements;
    fitsfile *new_fptr;

    nelements = stats.dim[0] * stats.dim[1];
    fpixel[0] = 1;
    fpixel[1] = 1;


    /* Create a new File, overwriting existing*/
    if (fits_create_file(&new_fptr, newFilename.toAscii(), &status))
    {
        fits_report_error(stderr, status);
        return status;
    }

    /* Copy ALL contents */
    if (fits_copy_file(fptr, new_fptr, 1, 1, 1, &status))
    {
        fits_report_error(stderr, status);
        return status;
    }

    /* close current file */
    if (fits_close_file(fptr, &status))
    {
        fits_report_error(stderr, status);
        return status;
    }

    if (tempFile)
    {
        QFile::remove(filename);
        tempFile = false;
    }

    filename = newFilename;

    fptr = new_fptr;

    /* Write Data */
    if (fits_write_pix(fptr, TFLOAT, fpixel, nelements, image_buffer, &status))
    {
        fits_report_error(stderr, status);
        return status;
    }

    /* Write keywords */

    // Minimum
    if (fits_update_key(fptr, TDOUBLE, "DATAMIN", &(stats.min), "Minimum value", &status))
    {
        fits_report_error(stderr, status);
        return status;
    }

    // Maximum
    if (fits_update_key(fptr, TDOUBLE, "DATAMAX", &(stats.max), "Maximum value", &status))
    {
        fits_report_error(stderr, status);
        return status;
    }

    // ISO Date
    if (fits_write_date(fptr, &status))
    {
        fits_report_error(stderr, status);
        return status;
    }

    QString history = QString("Modified by KStars on %1").arg(QDateTime::currentDateTime().toString("yyyy-MM-ddThh:mm:ss"));
    // History
    if (fits_write_history(fptr, history.toAscii(), &status))
    {
        fits_report_error(stderr, status);
        return status;
    }

    return status;
}
Beispiel #11
0
int hpic_fits_vecindx_write(char *filename, char *creator, char *extname,
                            char *comment, hpic_vec_int * indx,
                            hpic_vec_fltarr * vecs, char **vecnames,
                            char **vecunits, hpic_keys * keys)
{

  size_t i, j, k, m;
  fitsfile *fp;
  int ret = 0;
  int bitpix = SHORT_IMG;
  int nax = 0;
  long axes[] = { 0, 0 };
  int total;
  int type;
  long rows;
  long frow = 1;
  long fsamp = 1;
  size_t veclen;
  char **vectypes;
  char **names;
  char **units;
  size_t nvecs = hpic_vec_fltarr_n_get(vecs);
  hpic_vec_float *tempvec;

  if (nvecs == 0) {
    HPIC_ERROR(HPIC_ERR_FITS, "must specify more than zero vectors!");
  }
  if (!indx) {
    HPIC_ERROR(HPIC_ERR_ACCESS, "index vector is not allocated");
  }
  for (i = 0; i < nvecs; i++) {
    tempvec = hpic_vec_fltarr_get(vecs, i);
    if (!tempvec) {
      HPIC_ERROR(HPIC_ERR_ACCESS, "input vector is not allocated");
    }
  }
  vectypes = hpic_strarr_alloc(nvecs + 1);
  names = hpic_strarr_alloc(nvecs + 1);
  units = hpic_strarr_alloc(nvecs + 1);

  veclen = hpic_vec_int_n_get(indx);
  for (i = 0; i < nvecs; i++) {
    tempvec = hpic_vec_fltarr_get(vecs, i);
    if (veclen != hpic_vec_float_n_get(tempvec)) {
      HPIC_ERROR(HPIC_ERR_FITS, "all vectors must have the same length");
    }
  }

  /* setup column parameters */

  strncpy(vectypes[0], "1J", HPIC_STRNL);
  strncpy(names[0], "INDEX", HPIC_STRNL);
  strncpy(units[0], "", HPIC_STRNL);
  for (i = 1; i < nvecs + 1; i++) {
    strncpy(vectypes[i], "1E", HPIC_STRNL);
    strncpy(names[i], vecnames[i - 1], HPIC_STRNL);
    strncpy(units[i], vecunits[i - 1], HPIC_STRNL);
  }

  /* create file */
  if (fits_create_file(&fp, filename, &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  creating file");
  }

  /* create empty primary image */
  if (fits_create_img(fp, bitpix, nax, axes, &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  creating primary image");
  }

  /* write header */
  if (fits_write_comment(fp, "    ", &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  writing header comment 1");
  }
  if (fits_write_comment(fp, comment, &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  writing header comment 2");
  }
  if (fits_write_comment(fp, "    ", &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  writing header comment 3");
  }
  if (fits_write_date(fp, &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  writing date");
  }
  if (fits_write_key
      (fp, TSTRING, "CREATOR", creator, "Software creating the map", &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  writing creator");
  }

  /* write extension */
  if (fits_create_tbl
      (fp, BINARY_TBL, (long)veclen, (int)(nvecs + 1), names, vectypes, units,
       extname, &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  creating binary table");
  }
  if (fits_movabs_hdu(fp, 2, &type, &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  moving to extension");
  }

  /* write mandatory keywords */
  if (fits_write_comment(fp, "     ", &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  writing ext comment 1");
  }
  if (fits_write_comment
      (fp, "-----------------------------------------------", &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  writing ext comment 2");
  }
  if (fits_write_comment(fp, "            Data Specific Keywords    ", &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  writing ext comment 3");
  }
  if (fits_write_comment
      (fp, "-----------------------------------------------", &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  writing ext comment 4");
  }
  if (fits_write_comment(fp, "      ", &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  writing comment 5");
  }

  /* write optional keywords */

  hpic_keys_write(keys, fp, &ret);

  /* write the data and clean up */
  if (fits_write_col
      (fp, TINT, 1, frow, fsamp, (long)veclen, indx->data, &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  writing index column");
  }
  for (i = 0; i < nvecs; i++) {
    tempvec = hpic_vec_fltarr_get(vecs, i);
    if (fits_write_col
        (fp, TFLOAT, (int)(i + 2), frow, fsamp, (long)veclen, tempvec->data,
         &ret)) {
      fitserr(ret, "hpic_fits_vecindx_write:  writing data column");
    }
  }
  
  hpic_strarr_free(vectypes, nvecs + 1);
  hpic_strarr_free(names, nvecs + 1);
  hpic_strarr_free(units, nvecs + 1);

  if (fits_close_file(fp, &ret)) {
    fitserr(ret, "hpic_fits_vecindx_write:  closing file");
  }

  return ret;
}
Beispiel #12
0
int put_header(fitsfile *fptr, struct uvf_header *header, int gcount,
	       double refdat, char *origin)
{
  int naxis = 7;
  long pcount = 6;
  long naxes[7] = {0, 3, 1, 1, 1, 1, 1};
  float bscale = 1.0, bzero = 0.0;
  int one = 1,  zero = 0;
  double dfac1, dfac2, dref1, dref2, frac;
  char str[80];
  int status = 0;
  int ier, year, month, day;
  char datobs[16];

  /* Create the DATOBS string */

  slaDjcl(refdat, &year, &month, &day, &frac, &ier);
  if (ier != 0)
    fputs("Invalid DATOBS for FITS file.\n", stderr);
  sprintf(datobs, "%4.4d-%2.2d-%2.2d", year, month, day);

  /* Check for presence of INTTIM */

  if (header->index_inttim >=0)
    pcount = 7;

  /* Write required keywords. */

  naxes[2] = header->nstokes;
  naxes[4] = header->nif;
  fits_write_grphdr(fptr, 1, FLOAT_IMG, naxis, naxes, pcount, gcount,
		    1, &status);    
  fits_write_key(fptr, TFLOAT, "BSCALE", &bscale, 0, &status);
  fits_write_key(fptr, TFLOAT, "BZERO",  &bzero, 0, &status);
  
  /* Additional keywords. */

  fits_write_key(fptr, TSTRING, "OBJECT",   header->object,
		 "Source name", &status);
  fits_write_key(fptr, TSTRING, "TELESCOP", header->telescop,
		 0, &status);
  fits_write_key(fptr, TSTRING, "INSTRUME", header->instrume,
		 0, &status);
  fits_write_key(fptr, TSTRING, "OBSERVER", header->observer,
		 0, &status);
  fits_write_key(fptr, TSTRING, "DATE-OBS", datobs,
		 0, &status);
  fits_write_key(fptr, TSTRING, "BUNIT",    header->bunit,   
		 0,  &status);
  fits_write_key(fptr, TSTRING, "RADECSYS", header->radecsys,
		 0, &status);
  fits_write_key(fptr, TDOUBLE,  "EQUINOX",  &header->equinox, 
		 "Equinox of RA/Dec",   &status);
  fits_write_key(fptr, TDOUBLE, "EPOCH",     &header->equinox,
		 "Alternate name for EQUINOX", &status);
  fits_write_key(fptr, TDOUBLE, "OBSRA",    &header->obsra,
		 "Antenna pointing RA", &status);
  fits_write_key(fptr, TDOUBLE, "OBSDEC",   &header->obsdec,
		 "Antenna pointing Dec", &status);

  /* FITS coordinate parameters */
  
  fits_write_key(fptr, TSTRING, "CTYPE2", "COMPLEX", "1=real, 2=imag, 3=weight", &status);
  fits_write_key(fptr, TINT,    "CRVAL2", &one,  0, &status);
  fits_write_key(fptr, TINT,    "CDELT2", &one,  0, &status);
  fits_write_key(fptr, TINT,    "CRPIX2", &one,  0, &status);

  fits_write_key(fptr, TSTRING, "CTYPE3", "STOKES", "Correlator: -1=RR, -2=LL, -3=RL, -4=LR",&status);
  fits_write_key(fptr, TINT,    "CRVAL3", &header->stokes,  0, &status);
  fits_write_key(fptr, TINT,    "CDELT3", &header->delta_stokes, 0, &status);
  fits_write_key(fptr, TINT,    "CRPIX3", &one,       0, &status);

  fits_write_key(fptr, TSTRING, "CTYPE4", "FREQ","Frequency, Hz", &status);
  fits_write_key(fptr, TDOUBLE, "CRVAL4", &header->freq, 0, &status);
  fits_write_key(fptr, TDOUBLE, "CDELT4", &header->bw,   0, &status);
  fits_write_key(fptr, TINT,    "CRPIX4", &one,  0, &status);

  fits_write_key(fptr, TSTRING, "CTYPE5", "IF", "IF number",&status);
  fits_write_key(fptr, TINT,    "CRVAL5", &one, 0, &status);
  fits_write_key(fptr, TINT,    "CDELT5", &one, 0, &status);
  fits_write_key(fptr, TINT,    "CRPIX5", &one, 0, &status);

  fits_write_key(fptr, TSTRING, "CTYPE6", "RA", "Right ascension, degrees", &status);
  fits_write_key(fptr, TDOUBLE, "CRVAL6", &header->ra, 0, &status);
  fits_write_key(fptr, TINT,    "CDELT6", &zero, 0, &status);
  fits_write_key(fptr, TINT,    "CRPIX6", &one,  0, &status);

  fits_write_key(fptr, TSTRING, "CTYPE7", "DEC", "Declination, degrees", &status);
  fits_write_key(fptr, TDOUBLE, "CRVAL7", &header->dec, 0, &status);
  fits_write_key(fptr, TINT,    "CDELT7", &zero, 0, &status);
  fits_write_key(fptr, TINT,    "CRPIX7", &one,  0, &status);

  /* FITS random parameters. */

  fits_write_key(fptr, TSTRING, "PTYPE1", "UU", "baseline u projection, seconds", &status);
  fits_write_key(fptr, TINT,    "PSCAL1", &one,  0, &status);
  fits_write_key(fptr, TINT,    "PZERO1", &zero, 0, &status);
  fits_write_key(fptr, TSTRING, "PTYPE2", "VV", "baseline v projection, seconds", &status);
  fits_write_key(fptr, TINT,    "PSCAL2", &one,  0, &status);
  fits_write_key(fptr, TINT,    "PZERO2", &zero, 0, &status);
  fits_write_key(fptr, TSTRING, "PTYPE3", "WW", "baseline w projection, seconds", &status);
  fits_write_key(fptr, TINT,    "PSCAL3", &one,  0, &status);
  fits_write_key(fptr, TINT,    "PZERO3", &zero, 0, &status);

  fits_write_key(fptr, TSTRING, "PTYPE4", "BASELINE", "256*ANT1 + ANT2", &status);
  fits_write_key(fptr, TINT,    "PSCAL4", &one,  0, &status);
  fits_write_key(fptr, TINT,    "PZERO4", &zero, 0, &status);

  dfac1 = 1.0;
  dref1 = refdat + 2400000.5; /* convert MJD to JD */
  fits_write_key(fptr, TSTRING, "PTYPE5", "DATE", "UTC Julian Date part 1", &status);
  fits_write_key(fptr, TDOUBLE, "PSCAL5", &dfac1, "Days", &status);
  fits_write_key(fptr, TDOUBLE, "PZERO5", &dref1,  0, &status);
  
  dfac2 = 1.0/86400.0;
  dref2 = 0.0;
  fits_write_key(fptr, TSTRING, "PTYPE6", "DATE", "UTC Julian Date part 2", &status);
  fits_write_key(fptr, TDOUBLE, "PSCAL6", &dfac2, "Days/86400 (sec)", &status);
  fits_write_key(fptr, TFLOAT,  "PZERO6", &dref2, 0, &status);
  if (pcount >= 7) {
    fits_write_key(fptr, TSTRING, "PTYPE7", "INTTIM", "Integration time (sec)", &status);
    fits_write_key(fptr, TINT,   "PSCAL7", &one, 0, &status);
    fits_write_key(fptr, TINT,   "PZERO7", &zero, 0, &status);
  }

  sprintf(str, "%.12s (run by %.12s on %.12s)", origin, 
	  getenv("USER"), getenv("HOST"));
  fits_write_key(fptr, TSTRING, "ORIGIN", str," ", &status);

  /* Date/time of file creation */

  fits_write_date(fptr, &status);
  fits_report_error(stderr, status);
  return status;
}
Beispiel #13
0
void write_profiles(float *prof,int nbins, int nchan, int nifs, FILE *out)/*includefile*/
{
  int i,j,c,b,k,m,year,month,day;
  float *profile,scale,offset,rms,epoch;
  double usec,tbin,tres,psec;
  static int first=1;
  struct EPN epn;

  int sta=0;
  short int sj;
  float x,binned_freq[16384],binned_weight[16384],
    binned_offset[16384],binned_scale[16384],binned_data[16384];
  int bitpix=8, naxis=0, nrcvr, nrows, ncols, col;
  static int subint_cnt;
  char datestr[10],timestr[8];
  char Cstr16[16], Estr16[16], Istr16[16];
  char *ttype[20], *tform[20], *tunit[20];
  long naxes[4];
  int junk,rah,ram,ded,dem,subint_hdu,hh,mm;
  float ss;
  int last_scanhdr_hdu;
  double ras,des,dx;
  char rastr[80], destr[80], sra[80], sde[80];
  char date_time[24];
  char *pch[MAX_BLKS];
  char site[MAX_BLKS][2];
  short int nspan[MAX_BLKS];
  short int ncoeff[MAX_BLKS];
  double rfreq[MAX_BLKS];
  double rmjd[MAX_BLKS];
  double rphase[MAX_BLKS];
  double lgfiterr[MAX_BLKS];
  double f0[MAX_BLKS];
  double coeff[MAX_BLKS][MAX_COEFF];
  static double srcl, srcb;
  /* For Pulsar History BINTABLE */
 
  static char *PHtype[18] = {
    "DATE_PRO","PROC_CMD","POL_TYPE","NPOL    ","NBIN    ","NBIN_PRD","TBIN    ","CTR_FREQ",
    "NCHAN   ","CHAN_BW ","PAR_CORR","RM_CORR ","DEDISP  ","DDS_MTHD","SC_MTHD ","CAL_MTHD",
    "CAL_FILE","RFI_MTHD"
  };
  
  static char *PHform[18] = {
    "24A     ","80A     ","8A      ","1I      ","1I      ","1I      ","1D      ","1D      ",
    "1I      ","1D      ","1I      ","1I      ","1I      ","32A     ","32A     ","32A     ",
    "32A     ","32A     "
  };
  
  static char *PHunit[18] = {
    "        ","        ","        ","        ","        ","        ","s       ","MHz     ",
    "        ","MHz     ","        ","        ","        ","        ","        ","        ",
    "        ","        "
  };

  /* subtract baseline from outgoing profiles if requested */
  if (userbase != 0.0) for (i=0;i<multiple*nbins*nifs*nchans;i++) 
    prof[i]-=userbase;

  /* multiply outgoing profiles by Jansky calibration factor if supplied */
  if (jyfactor != 0.0) for (i=0;i<multiple*nbins*nifs*nchans;i++) 
    prof[i]*=jyfactor;

  /* sum first two polarizations together if requested */
  if (totalpower && (nifs > 1)) {
    for (i=0;i<multiple*nbins*nchans;i++) 
      prof[i]+=prof[i+multiple*nbins*nchans];
    nifs=1;
  }

  if (binary) {
    /* write out profiles in binary format */
    folding_period=pfld0*1000.0;
    tadd=tstart;
    tstart=tstart+tsta/86400.0;
    npuls=pulsecount;
    fold_header();
    tstart=tadd;
    for (i=0; i<nifs; i++) {
      for (c=0; c<nchan; c++) {
	for (b=0; b<nbins; b++) 
	  fwrite(&prof[i*nchan*nbins+c*nbins+b],sizeof(float),1,out);
      }
    }
  } else if (stream) {
    /* write out profiles as ASCII streams with START/STOP boundaries */
    k=0;
    for (i=0;i<nifs;i++) {
      for (c=0;c<nchan;c++) {
	fprintf(out,"#START %d %f %f\n",nbins,tsta,fch1+foff*(float)c);
	for (m=0;m<multiple;m++) {
	  for (b=0;b<nbins;b++) {
	    fprintf(out,"%d %f\n",b+m*nbins,prof[i*nchan*nbins+c*nbins+b]);
	  }
	}
	fprintf(out,"#STOP\n");
      }
    }
  } else if (asciipol) {
    /* write profiles in format for Jim's polarization code */
    for (b=0;b<nbins;b++) 
      for (i=0;i<nifs;i++)
	for (c=0;c<nchan;c++) 
	  fprintf(out,"%d %d %d %f\n",b,i,c,prof[i*nchan*nbins+c*nbins+b]);
  } else if (ascii) {
    fprintf(output,"# %.1f %.7f %.10f %ld %.3f %.3f %d %c %d %s\n",
     floor(tstart),(tstart-floor(tstart))*86400.0+tsta,pfld0,pulsecount,fch1,refdm,nbins,tempo_site(telescope_id),1,source_name);
    for (b=0;b<nbins;b++) {
      fprintf(out,"%d",b+1);
      for (i=0;i<nifs;i++) {
	for (c=0;c<nchan;c++) fprintf(out," %f",prof[i*nchan*nbins+c*nbins+b]);
      }
      fprintf(out,"\n");
    }
#ifdef PSRFITS
  } else if (psrfits) {
    if (first) {
      first=0;
      /* write profile in PSRFITS format */
      fits_create_file(&fits, "stdout", &sta);
      fits_create_img(fits,bitpix,naxis,naxes,&sta);
      fits_write_date(fits,&sta);
      /* Get DateTime string - required in various BINTABLEs */
      fits_get_system_time(date_time,&junk,&sta);
      fits_update_key(fits,TSTRING,"HDRVER","1.19","Header version",&sta);
      fits_update_key(fits,TSTRING,"OBSERVER",culprits,
		      "Observer name(s)",&sta);
      fits_update_key(fits,TSTRING,"PROJID",project,"Project name",&sta);
      fits_update_key(fits,TSTRING,"TELESCOP",telescope_name(telescope_id),
		      "Telescope name", &sta);
      fits_update_key(fits,TSTRING,"BACKEND",backend_name(machine_id),
		      "Backend ID",&sta);
      if (nifs>1) 
	nrcvr=2;
      else
	nrcvr=1;
      fits_update_key(fits,TINT,"NRCVR",&nrcvr,
		      "Number of receiver channels (I)",&sta);
      fits_update_key(fits,TSTRING,"OBS_MODE", "PSR",
		      "(PSR, CAL, SEARCH)", &sta);
      fits_update_key(fits,TSTRING,"SRC_NAME", source_name,
		      "Source or scan ID", &sta);
      fits_update_key(fits,TSTRING,"COORD_MD", "J2000",
		      "Coordinate mode (J2000, Gal, Ecliptic, etc.)", &sta);
      
      angle_split(src_raj,&rah,&ram,&ras);
      if (ras<10.0) 
	sprintf(sra,"0%.3f",ras);
      else
	sprintf(sra,"%.3f",ras);
      sprintf(rastr,"%02d:%02d:%s",rah,ram,sra);
      angle_split(src_dej,&ded,&dem,&des);
      if (des<10.0) 
	sprintf(sde,"0%.3f",des);
      else
	sprintf(sde,"%.3f",des);
      sprintf(destr,"%02d:%02d:%s",ded,dem,sde);
      cel2gal(rah,ram,ras,ded,dem,des,&srcl,&srcb);

      fits_update_key(fits, TSTRING, "STT_CRD1", rastr,
		      "Start coord 1 (hh:mm:ss.sss or ddd.ddd)", &sta);
      fits_update_key(fits, TSTRING, "STT_CRD2", destr,
		      "Start coord 2 (-dd:mm:ss.sss or -dd.ddd)", &sta);
      fits_update_key(fits, TSTRING, "TRK_MODE", "TRACK",
		      "Track mode (TRACK, SCANGC, SCANLAT)", &sta);
      fits_update_key(fits, TSTRING, "STP_CRD1", rastr,
		      "Stop coord 1 (hh:mm:ss.sss or ddd.ddd)", &sta);
      fits_update_key(fits, TSTRING, "STP_CRD2", destr,
		      "Stop coord 2 (-dd:mm:ss.sss or -dd.ddd)", &sta);
      fits_update_key(fits, TSTRING, "CAL_MODE", "OFF",
		      "Cal mode (OFF, SYNC, EXT1, EXT2)", &sta);
      fits_create_tbl(fits,BINARY_TBL,0,18,PHtype,
		      PHform,PHunit,"HISTORY",&sta);
      pch[0] = date_time;
      fits_write_col(fits,  TSTRING, 1, 1, 1, 1, pch, &sta);
      pch[0] = "SIGPROC";
      fits_write_col(fits,  TSTRING, 2, 1, 1, 1, pch, &sta);
      pch[0] = "??";
      fits_write_col(fits,  TSTRING, 3, 1, 1, 1, pch, &sta);
      /* Nr of pols  - i.e. actually written out */
      sj = nifs;
      fits_write_col(fits, TSHORT, 4, 1, 1, 1, &sj, &sta );
      
      /* Nr of bins per product (0 for SEARCH mode) */
      sj = nbins;
      fits_write_col( fits, TSHORT, 5, 1, 1, 1, &sj, &sta );
      
      /* Nr of bins per period */
      fits_write_col( fits, TSHORT, 6, 1, 1, 1, &sj, &sta );
      
      /* Bin time */
      dx =  folding_period/sj;
      fits_write_col( fits, TDOUBLE, 7, 1, 1, 1, &dx, &sta );
      
      /* Centre freq. */
      dx = ((double)(nchans/2)-1.0)*foff+fch1;
      fits_write_col( fits, TDOUBLE, 8, 1, 1, 1, &dx, &sta );
      
      /* Number of channels */
      sj = nchans;
      fits_write_col( fits, TSHORT, 9, 1, 1, 1, &sj, &sta );
      
      /* Channel bandwidth */
      dx = foff;
      fits_write_col( fits, TDOUBLE, 10, 1, 1, 1, &dx, &sta );
      
      /* Create frequency array for later */
      /* Get freq. of first channel */
      if ((fch1==0.0) && (foff==0.0)) {
	for (i=0; i<nchans; i++) binned_freq[i]=(float) frequency_table[i];
      } else {
	for (i=0; i<nchans; i++) 
	  binned_freq[i]=fch1+i*foff;
      }
      
      for (i=0; i<16384; i++) {
	binned_scale[i]=1.0;
	binned_offset[i]=0.0;
	binned_weight[i]=1.0;
      }
      
      sj = 0;
      /* Parallactic angle correction applied */
      fits_write_col( fits, TSHORT, 11, 1, 1, 1, &sj, &sta );
      /* RM correction applied */
      fits_write_col( fits, TSHORT, 12, 1, 1, 1, &sj, &sta );
      /* Data dedispersed */
      fits_write_col( fits, TSHORT, 13, 1, 1, 1, &sj, &sta );
      /* Dedispersion method */
      pch[0] = "NONE";
      fits_write_col( fits, TSTRING, 14, 1, 1, 1, pch, &sta );
      /* Scattered power correction method */
      pch[0] = "NONE";
      fits_write_col( fits, TSTRING, 15, 1, 1, 1, pch, &sta );
      /* Calibration method */
      pch[0] = "NONE";
      fits_write_col( fits, TSTRING, 16, 1, 1, 1, pch, &sta );
      /* Name of calibration file */
      pch[0] = "NONE";
      fits_write_col( fits, TSTRING, 17, 1, 1, 1, pch, &sta );
      /* RFI excision method */
      pch[0] = "NONE";
      fits_write_col( fits, TSTRING, 18, 1, 1, 1, pch, &sta );
      /* Store last header hdu number */
      fits_get_hdu_num( fits, &last_scanhdr_hdu );

      subint_cnt=1;
      /* Add START TIME to primary HDU */
      /* Move to primary HDU */
      fits_movabs_hdu( fits, 1, NULL, &sta );
      cal(tstart,&epn.year,&epn.month,&epn.day);
      sprintf(datestr,"%4d-%02d-%02d",epn.year,epn.month,epn.day);
      fits_update_key( fits, TSTRING, "STT_DATE", datestr,
		       "Start UT date (YYYY-MM-DD)", &sta);
      uttime(tstart,&hh,&mm,&ss);
      sprintf(timestr,"%02d:%02d:%02d",hh,mm,ss);
      fits_update_key( fits, TSTRING, "STT_TIME", timestr,
		       "Start UT (hh:mm:ss)", &sta);
      dx=86400*(tstart-floor(tstart));
      fits_update_key( fits, TINT, "STT_SMJD", &dx,
		     "[s] Start time (sec past UTC 00h) (J)", &sta);
      /* Move to last created HDU in scan header */
      fits_movabs_hdu( fits, last_scanhdr_hdu, NULL, &sta );

      /* Create SUBINT BINTABLE */
      ttype[0] = "ISUBINT ";/* Subint number. If NAXIS=-1, 0 indicates EOD. */
      tform[0] = "1J      ";
      tunit[0] = "";
      ttype[1] = "INDEXVAL";    /* Optionally used if INT_TYPE != TIME */
      tform[1] = "1D      ";
      tunit[1] = "";
      ttype[2] = "TSUBINT ";    /* [s] Length of subintegration */
      tform[2] = "1D      ";
      tunit[2] = "";
      ttype[3] = "OFFS_SUB"; /* [s] Offset from Start UTC of subint centre */
      tform[3] = "1D      ";
      tunit[3] = "";
      ttype[4] = "LST_SUB ";    /* [s] LST at subint centre */
      tform[4] = "1D      ";
      tunit[4] = "";
      ttype[5] = "RA_SUB  ";    /* [turns] RA (J2000) at subint centre */
      tform[5] = "1D      ";
      tunit[5] = "";
      ttype[6] = "DEC_SUB ";    /* [turns] Dec (J2000) at subint centre */
      tform[6] = "1D      ";
      tunit[6] = "";
      ttype[7] = "GLON_SUB";    /* [deg] Gal longitude at subint centre */
      tform[7] = "1D      ";
      tunit[7] = "";
      ttype[8] = "GLAT_SUB";    /* [deg] Gal latitude at subint centre */
      tform[8] = "1D      ";
      tunit[8] = "";
      ttype[9] = "FD_ANG  ";    /* [deg] Feed angle at subint centre */
      tform[9] = "1E      ";
      tunit[9] = "";
      ttype[10] = "POS_ANG ";/*[deg] Position angle of feed at subint centre */
      tform[10] = "1E      ";
      tunit[10] = "";
      ttype[11] = "PAR_ANG ";    /* [deg] Parallactic angle at subint centre */
      tform[11] = "1E      ";
      tunit[11] = "";
      ttype[12] = "TEL_AZ  ";    /* [deg] Telescope azimuth at subint centre */
      tform[12] = "1E      ";
      tunit[12] = "";
      ttype[13] = "TEL_ZEN ";/*[deg] Telescope zenith angle at subint centre */
      tform[13] = "1E      ";
      tunit[13] = "";

      sprintf( Cstr16, "%dE", nchans );
      ttype[14] = "DAT_FREQ";
      tform[14] = Cstr16;
      tunit[14] = "";
      ttype[15] = "DAT_WTS ";
      tform[15] = Cstr16;
      tunit[15] = "";
      
      sprintf( Estr16, "%dE", nifs*nchans );
      ttype[16] = "DAT_OFFS";
      tform[16] = Estr16;
      tunit[16] = "";
      ttype[17] = "DAT_SCL ";
      tform[17] = Estr16;
      tunit[17] = "";
      
      sprintf( Istr16, "%dE", nifs*nchans*nbins );
      ttype[18] = "DATA    ";
      tform[18] = Istr16;
      tunit[18] = "Jy      ";
      
      nrows = 0; /* naxis2 - Let CFITSIO sort this out */
      ncols = 19; /* tfields */
      fits_create_tbl( fits, BINARY_TBL, nrows, ncols, 
		       ttype, tform, tunit, "SUBINT  ", &sta);
      
      /* Add dimensions of column 'ncols' = SUBINT Data */
      naxes[0] = nbins;
      naxes[1] = nchans;
      naxes[2] = nifs;
    
      fits_write_tdim( fits, ncols, 3, naxes, &sta );
      
      /* Add keywords */
      fits_update_key( fits, TSTRING, "INT_TYPE", "TIME",
		       "Time axis (TIME, BINPHSPERI, BINLNGASC, etc)", &sta);
      
      fits_update_key( fits, TSTRING, "INT_UNIT", "SEC",
		       "Unit of time axis (SEC, PHS (0-1), DEG)", &sta);
      
      fits_update_key( fits, TINT, "NCH_FILE", &nchans,
		       "Number of channels/sub-bands in this file (I)", &sta);
      j = 0;
      fits_update_key( fits, TINT, "NCH_STRT", &j,
		     "Start channel/sub-band number (0 to NCHAN-1) (I)", &sta);
    
      /* Store subint hdu number */
      fits_get_hdu_num( fits, &subint_hdu );
    }
    
    /* Write SUBINT BINTABLE columns */
    
    /* Fill in columns of table */
    col = 1;
    
    /* Subint number. If NAXIS=-1, 0 indicates EOD. */
    j=subint_cnt;
    fits_write_col( fits, TINT, col, subint_cnt, 1, 1, &j, &sta );
    col++;
    
    /* INDEXVAL - Optionally used if INT_TYPE != TIME */
    dx = 0.0;
    fits_write_col( fits, TDOUBLE, col, subint_cnt, 1, 1, &dx, &sta );
    col++;
    
    /* [s] Length of subint */
    fits_write_col( fits, TDOUBLE, col, subint_cnt, 1, 1, &dump_time, &sta );
    col++;
    
    /* [s] Offset from Start UTC of subint centre */
    dx = 0.0;
    fits_write_col( fits, TDOUBLE, col, subint_cnt, 1, 1, &dx, &sta );
    col++;
    
    /* [s] LST at subint centre */
    dx=0.0;
    fits_write_col( fits, TDOUBLE, col, subint_cnt, 1, 1, &dx, &sta );
    col++;
    
    /* [turns] RA (J2000) at subint centre */
    dx=src_raj/360.0;
    fits_write_col( fits, TDOUBLE, col, subint_cnt, 1, 1, &dx, &sta );
    col++;
    
    /* [turns] Dec (J2000) at subint centre */
    dx=src_dej/360.0;
    fits_write_col( fits, TDOUBLE, col, subint_cnt, 1, 1, &dx, &sta );
    col++;
    
    /* [deg] Gal longitude at subint centre */
    dx=srcl;
    fits_write_col( fits, TDOUBLE, col, subint_cnt, 1, 1, &dx, &sta );
    col++;

    /* [deg] Gal latitude at subint centre */
    dx=srcb;
    fits_write_col( fits, TDOUBLE, col, subint_cnt, 1, 1, &dx, &sta );
    col++;

    /* [deg] Feed angle at subint centre */
    x=0.0;
    fits_write_col( fits, TFLOAT, col, subint_cnt, 1, 1, &x, &sta );
    col++;

    /* [deg] Parallactic angle at subint centre */

    /* [deg] Position angle of feed at subint centre */
    fits_write_col( fits, TFLOAT, col, subint_cnt, 1, 1, &x, &sta );
    col++;

    /* [deg] Parallactic angle at subint centre */
    fits_write_col( fits, TFLOAT, col, subint_cnt, 1, 1, &x, &sta );
    col++;

    /* [deg] Telescope azimuth at subint centre */
    x=(float) az_start;
    fits_write_col( fits, TFLOAT, col, subint_cnt, 1, 1, &x, &sta );
    col++;

    /* [deg] Telescope zenith angle at subint centre */
    x=(float) za_start;
    fits_write_col( fits, TFLOAT, col, subint_cnt, 1, 1, &x, &sta );
    col++;

    /* Centre freq. for each channel - NCHAN floats */
    fits_write_col( fits, TFLOAT, col, subint_cnt, 1,nchans,binned_freq,&sta );
    col++;

    /* Weights for each channel -  NCHAN floats */
    fits_write_col( fits, TFLOAT, col, subint_cnt, 1, nchans,
		    binned_weight, &sta );
    col++;

    /* Data offset for each channel - NCHAN*NPOL floats */
    fits_write_col( fits, TFLOAT, col, subint_cnt, 1, nchans*nifs,
		    binned_offset, &sta );
    col++;

    /* Data scale factor for each channel - NCHAN*NPOL floats */
    fits_write_col( fits, TFLOAT, col, subint_cnt, 1, nchans*nifs, 
		    binned_scale, &sta );
    col++;

    /* Subint data table - Dimensions of data table = (NBIN,NCHAN,NPOL) */
    for (i=0;i<nchans*nifs*nbins;i++) binned_data[i]=prof[i];

    fits_write_col(fits,TFLOAT,col, subint_cnt, 1, nbins*nchans*nifs, 
		   binned_data, &sta );

    subint_cnt++;
    if (sta) fits_report_error(stderr,sta);
#endif
  } else {
    /* EPN format requested - set up some general EPN variables */
    sprintf(epn.history,"%s %s fast-sampled data reduced using fold",
	    telescope_name(telescope_id),backend_name(machine_id));
    while (strlen(epn.history)<65) strcat(epn.history," ");
    strcpy(epn.jname,"");
    strcpy(epn.cname,"");
    epn.pbar=pfld0;
    epn.dm=refdm;
    epn.rm=0.0;
    strcpy(epn.catref,"none");
    strcpy(epn.bibref,"none");
    epn.raj=0.0;
    epn.dec=0.0;
    strcpy(epn.telname,telescope_name(telescope_id));
    epn.epoch=(float) floor(tstart);
    epn.opos=0.0;
    epn.paflag=' ';
    epn.timflag='U';
    epn.xtel=0.0;
    epn.ytel=0.0;
    epn.ztel=0.0;
    cal((double)epn.epoch,&epn.year,&epn.month,&epn.day);
    epn.scanno=0;
    epn.subscan=0;
    epn.npol=nifs;
    epn.nfreq=nchan;
    epn.nbins=nbins;
    epn.tbin=1.0e6*pfld0/(double)nbins;
    epn.nint=0;
    epn.ncal=0;
    epn.lcal=0;
    epn.tres=epn.tbin;
    epn.fluxflag='U';
    epn.navg=1;
    strcpy(epn.uf,"MHz ");
    epn.df=1000.0*fabs(foff);
    strcpy(epn.ud,"kHz ");
    if (epn.df>=10000.0) {
      epn.df/=1000.0;
      strcpy(epn.ud,"MHz ");
    }
    epn.tstart=(tstart-floor(tstart))*86400.0+tsta;
    epn.tstart*=1.0e6;
    epn.iprofile=(unsigned long *) malloc(epn.nbins*sizeof(long));
    profile = (float *) malloc(sizeof(float)*nbins);
    for (i=0;i<nifs;i++) {
      strcpy(epn.idfield,"I");
      for (c=0;c<nchan;c++) {
	for (b=0;b<nbins;b++) {
	  profile[b]=prof[i*nchan*nbins+c*nbins+b];
	}
	scale_prof(profile,nbins,epn.iprofile,&epn.scale,&epn.offset);
	epn.f0=fch1+foff*c;
	epn.nband=c+1;
	epn.papp=pfld0;
	epn.rms=0.0;
	epn.tres=tbin=1.0e6*pfld0*window/(double)nbins;
	if (c==0) write_epn_header(out,epn);
	write_epn_subheader(out,epn);
      }
    }
    fflush(out);
    free(profile);
    free(epn.iprofile);
  }
}