1004 lines
35 KiB
C
1004 lines
35 KiB
C
/* This file, putcoli.c, contains routines that write data elements to */
|
|
/* a FITS image or table, with short datatype. */
|
|
|
|
/* The FITSIO software was written by William Pence at the High Energy */
|
|
/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */
|
|
/* Goddard Space Flight Center. */
|
|
|
|
#include <limits.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "fitsio2.h"
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffppri( fitsfile *fptr, /* I - FITS file pointer */
|
|
long group, /* I - group to write (1 = 1st group) */
|
|
LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */
|
|
LONGLONG nelem, /* I - number of values to write */
|
|
short *array, /* I - array of values that are written */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Write an array of values to the primary array. Data conversion
|
|
and scaling will be performed if necessary (e.g, if the datatype of
|
|
the FITS array is not the same as the array being written).
|
|
*/
|
|
{
|
|
long row;
|
|
short nullvalue;
|
|
|
|
/*
|
|
the primary array is represented as a binary table:
|
|
each group of the primary array is a row in the table,
|
|
where the first column contains the group parameters
|
|
and the second column contains the image itself.
|
|
*/
|
|
|
|
if (fits_is_compressed_image(fptr, status))
|
|
{
|
|
/* this is a compressed image in a binary table */
|
|
|
|
|
|
fits_write_compressed_pixels(fptr, TSHORT, firstelem, nelem,
|
|
0, array, &nullvalue, status);
|
|
return(*status);
|
|
}
|
|
|
|
row=maxvalue(1,group);
|
|
|
|
ffpcli(fptr, 2, row, firstelem, nelem, array, status);
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffppni( fitsfile *fptr, /* I - FITS file pointer */
|
|
long group, /* I - group to write(1 = 1st group) */
|
|
LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */
|
|
LONGLONG nelem, /* I - number of values to write */
|
|
short *array, /* I - array of values that are written */
|
|
short nulval, /* I - undefined pixel value */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Write an array of values to the primary array. Data conversion
|
|
and scaling will be performed if necessary (e.g, if the datatype of the
|
|
FITS array is not the same as the array being written). Any array values
|
|
that are equal to the value of nulval will be replaced with the null
|
|
pixel value that is appropriate for this column.
|
|
*/
|
|
{
|
|
long row;
|
|
short nullvalue;
|
|
|
|
/*
|
|
the primary array is represented as a binary table:
|
|
each group of the primary array is a row in the table,
|
|
where the first column contains the group parameters
|
|
and the second column contains the image itself.
|
|
*/
|
|
|
|
if (fits_is_compressed_image(fptr, status))
|
|
{
|
|
/* this is a compressed image in a binary table */
|
|
|
|
nullvalue = nulval; /* set local variable */
|
|
fits_write_compressed_pixels(fptr, TSHORT, firstelem, nelem,
|
|
1, array, &nullvalue, status);
|
|
return(*status);
|
|
}
|
|
|
|
row=maxvalue(1,group);
|
|
|
|
ffpcni(fptr, 2, row, firstelem, nelem, array, nulval, status);
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffp2di(fitsfile *fptr, /* I - FITS file pointer */
|
|
long group, /* I - group to write(1 = 1st group) */
|
|
LONGLONG ncols, /* I - number of pixels in each row of array */
|
|
LONGLONG naxis1, /* I - FITS image NAXIS1 value */
|
|
LONGLONG naxis2, /* I - FITS image NAXIS2 value */
|
|
short *array, /* I - array to be written */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Write an entire 2-D array of values to the primary array. Data conversion
|
|
and scaling will be performed if necessary (e.g, if the datatype of the
|
|
FITS array is not the same as the array being written).
|
|
*/
|
|
{
|
|
/* call the 3D writing routine, with the 3rd dimension = 1 */
|
|
|
|
ffp3di(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
|
|
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffp3di(fitsfile *fptr, /* I - FITS file pointer */
|
|
long group, /* I - group to write(1 = 1st group) */
|
|
LONGLONG ncols, /* I - number of pixels in each row of array */
|
|
LONGLONG nrows, /* I - number of rows in each plane of array */
|
|
LONGLONG naxis1, /* I - FITS image NAXIS1 value */
|
|
LONGLONG naxis2, /* I - FITS image NAXIS2 value */
|
|
LONGLONG naxis3, /* I - FITS image NAXIS3 value */
|
|
short *array, /* I - array to be written */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Write an entire 3-D cube of values to the primary array. Data conversion
|
|
and scaling will be performed if necessary (e.g, if the datatype of the
|
|
FITS array is not the same as the array being written).
|
|
*/
|
|
{
|
|
long tablerow, ii, jj;
|
|
long fpixel[3]= {1,1,1}, lpixel[3];
|
|
LONGLONG nfits, narray;
|
|
/*
|
|
the primary array is represented as a binary table:
|
|
each group of the primary array is a row in the table,
|
|
where the first column contains the group parameters
|
|
and the second column contains the image itself.
|
|
*/
|
|
|
|
if (fits_is_compressed_image(fptr, status))
|
|
{
|
|
/* this is a compressed image in a binary table */
|
|
lpixel[0] = (long) ncols;
|
|
lpixel[1] = (long) nrows;
|
|
lpixel[2] = (long) naxis3;
|
|
|
|
fits_write_compressed_img(fptr, TSHORT, fpixel, lpixel,
|
|
0, array, NULL, status);
|
|
|
|
return(*status);
|
|
}
|
|
|
|
tablerow=maxvalue(1,group);
|
|
|
|
if (ncols == naxis1 && nrows == naxis2) /* arrays have same size? */
|
|
{
|
|
/* all the image pixels are contiguous, so write all at once */
|
|
ffpcli(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
|
|
return(*status);
|
|
}
|
|
|
|
if (ncols < naxis1 || nrows < naxis2)
|
|
return(*status = BAD_DIMEN);
|
|
|
|
nfits = 1; /* next pixel in FITS image to write to */
|
|
narray = 0; /* next pixel in input array to be written */
|
|
|
|
/* loop over naxis3 planes in the data cube */
|
|
for (jj = 0; jj < naxis3; jj++)
|
|
{
|
|
/* loop over the naxis2 rows in the FITS image, */
|
|
/* writing naxis1 pixels to each row */
|
|
|
|
for (ii = 0; ii < naxis2; ii++)
|
|
{
|
|
if (ffpcli(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
|
|
return(*status);
|
|
|
|
nfits += naxis1;
|
|
narray += ncols;
|
|
}
|
|
narray += (nrows - naxis2) * ncols;
|
|
}
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffpssi(fitsfile *fptr, /* I - FITS file pointer */
|
|
long group, /* I - group to write(1 = 1st group) */
|
|
long naxis, /* I - number of data axes in array */
|
|
long *naxes, /* I - size of each FITS axis */
|
|
long *fpixel, /* I - 1st pixel in each axis to write (1=1st) */
|
|
long *lpixel, /* I - last pixel in each axis to write */
|
|
short *array, /* I - array to be written */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Write a subsection of pixels to the primary array or image.
|
|
A subsection is defined to be any contiguous rectangular
|
|
array of pixels within the n-dimensional FITS data file.
|
|
Data conversion and scaling will be performed if necessary
|
|
(e.g, if the datatype of the FITS array is not the same as
|
|
the array being written).
|
|
*/
|
|
{
|
|
long tablerow;
|
|
LONGLONG fpix[7], dimen[7], astart, pstart;
|
|
LONGLONG off2, off3, off4, off5, off6, off7;
|
|
LONGLONG st10, st20, st30, st40, st50, st60, st70;
|
|
LONGLONG st1, st2, st3, st4, st5, st6, st7;
|
|
long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
|
|
|
|
if (*status > 0)
|
|
return(*status);
|
|
|
|
if (fits_is_compressed_image(fptr, status))
|
|
{
|
|
/* this is a compressed image in a binary table */
|
|
|
|
fits_write_compressed_img(fptr, TSHORT, fpixel, lpixel,
|
|
0, array, NULL, status);
|
|
|
|
return(*status);
|
|
}
|
|
|
|
if (naxis < 1 || naxis > 7)
|
|
return(*status = BAD_DIMEN);
|
|
|
|
tablerow=maxvalue(1,group);
|
|
|
|
/* calculate the size and number of loops to perform in each dimension */
|
|
for (ii = 0; ii < 7; ii++)
|
|
{
|
|
fpix[ii]=1;
|
|
irange[ii]=1;
|
|
dimen[ii]=1;
|
|
}
|
|
|
|
for (ii = 0; ii < naxis; ii++)
|
|
{
|
|
fpix[ii]=fpixel[ii];
|
|
irange[ii]=lpixel[ii]-fpixel[ii]+1;
|
|
dimen[ii]=naxes[ii];
|
|
}
|
|
|
|
i1=irange[0];
|
|
|
|
/* compute the pixel offset between each dimension */
|
|
off2 = dimen[0];
|
|
off3 = off2 * dimen[1];
|
|
off4 = off3 * dimen[2];
|
|
off5 = off4 * dimen[3];
|
|
off6 = off5 * dimen[4];
|
|
off7 = off6 * dimen[5];
|
|
|
|
st10 = fpix[0];
|
|
st20 = (fpix[1] - 1) * off2;
|
|
st30 = (fpix[2] - 1) * off3;
|
|
st40 = (fpix[3] - 1) * off4;
|
|
st50 = (fpix[4] - 1) * off5;
|
|
st60 = (fpix[5] - 1) * off6;
|
|
st70 = (fpix[6] - 1) * off7;
|
|
|
|
/* store the initial offset in each dimension */
|
|
st1 = st10;
|
|
st2 = st20;
|
|
st3 = st30;
|
|
st4 = st40;
|
|
st5 = st50;
|
|
st6 = st60;
|
|
st7 = st70;
|
|
|
|
astart = 0;
|
|
|
|
for (i7 = 0; i7 < irange[6]; i7++)
|
|
{
|
|
for (i6 = 0; i6 < irange[5]; i6++)
|
|
{
|
|
for (i5 = 0; i5 < irange[4]; i5++)
|
|
{
|
|
for (i4 = 0; i4 < irange[3]; i4++)
|
|
{
|
|
for (i3 = 0; i3 < irange[2]; i3++)
|
|
{
|
|
pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
|
|
|
|
for (i2 = 0; i2 < irange[1]; i2++)
|
|
{
|
|
if (ffpcli(fptr, 2, tablerow, pstart, i1, &array[astart],
|
|
status) > 0)
|
|
return(*status);
|
|
|
|
astart += i1;
|
|
pstart += off2;
|
|
}
|
|
st2 = st20;
|
|
st3 = st3+off3;
|
|
}
|
|
st3 = st30;
|
|
st4 = st4+off4;
|
|
}
|
|
st4 = st40;
|
|
st5 = st5+off5;
|
|
}
|
|
st5 = st50;
|
|
st6 = st6+off6;
|
|
}
|
|
st6 = st60;
|
|
st7 = st7+off7;
|
|
}
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffpgpi( fitsfile *fptr, /* I - FITS file pointer */
|
|
long group, /* I - group to write(1 = 1st group) */
|
|
long firstelem, /* I - first vector element to write(1 = 1st) */
|
|
long nelem, /* I - number of values to write */
|
|
short *array, /* I - array of values that are written */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Write an array of group parameters to the primary array. Data conversion
|
|
and scaling will be performed if necessary (e.g, if the datatype of
|
|
the FITS array is not the same as the array being written).
|
|
*/
|
|
{
|
|
long row;
|
|
|
|
/*
|
|
the primary array is represented as a binary table:
|
|
each group of the primary array is a row in the table,
|
|
where the first column contains the group parameters
|
|
and the second column contains the image itself.
|
|
*/
|
|
|
|
row=maxvalue(1,group);
|
|
|
|
ffpcli(fptr, 1L, row, firstelem, nelem, array, status);
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffpcli( fitsfile *fptr, /* I - FITS file pointer */
|
|
int colnum, /* I - number of column to write (1 = 1st col) */
|
|
LONGLONG firstrow, /* I - first row to write (1 = 1st row) */
|
|
LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */
|
|
LONGLONG nelem, /* I - number of values to write */
|
|
short *array, /* I - array of values to write */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Write an array of values to a column in the current FITS HDU.
|
|
The column number may refer to a real column in an ASCII or binary table,
|
|
or it may refer to a virtual column in a 1 or more grouped FITS primary
|
|
array. FITSIO treats a primary array as a binary table with
|
|
2 vector columns: the first column contains the group parameters (often
|
|
with length = 0) and the second column contains the array of image pixels.
|
|
Each row of the table represents a group in the case of multigroup FITS
|
|
images.
|
|
|
|
The input array of values will be converted to the datatype of the column
|
|
and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
|
|
*/
|
|
{
|
|
int tcode, maxelem2, hdutype, writeraw;
|
|
long twidth, incre;
|
|
long ntodo;
|
|
LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
|
|
double scale, zero;
|
|
char tform[20], cform[20];
|
|
char message[FLEN_ERRMSG];
|
|
|
|
char snull[20]; /* the FITS null value */
|
|
|
|
double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
|
|
void *buffer;
|
|
|
|
if (*status > 0) /* inherit input status value if > 0 */
|
|
return(*status);
|
|
|
|
buffer = cbuff;
|
|
|
|
/*---------------------------------------------------*/
|
|
/* Check input and get parameters about the column: */
|
|
/*---------------------------------------------------*/
|
|
if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
|
|
tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
|
|
&repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
|
|
return(*status);
|
|
maxelem = maxelem2;
|
|
|
|
if (tcode == TSTRING)
|
|
ffcfmt(tform, cform); /* derive C format for writing strings */
|
|
|
|
/*
|
|
if there is no scaling and the native machine format is not byteswapped,
|
|
then we can simply write the raw data bytes into the FITS file if the
|
|
datatype of the FITS column is the same as the input values. Otherwise,
|
|
we must convert the raw values into the scaled and/or machine dependent
|
|
format in a temporary buffer that has been allocated for this purpose.
|
|
*/
|
|
if (scale == 1. && zero == 0. &&
|
|
MACHINE == NATIVE && tcode == TSHORT)
|
|
{
|
|
writeraw = 1;
|
|
if (nelem < (LONGLONG)INT32_MAX) {
|
|
maxelem = nelem;
|
|
} else {
|
|
maxelem = INT32_MAX/2;
|
|
}
|
|
}
|
|
else
|
|
writeraw = 0;
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
/* Now write the pixels to the FITS column. */
|
|
/* First call the ffXXfYY routine to (1) convert the datatype */
|
|
/* if necessary, and (2) scale the values by the FITS TSCALn and */
|
|
/* TZEROn linear scaling parameters into a temporary buffer. */
|
|
/*---------------------------------------------------------------------*/
|
|
remain = nelem; /* remaining number of values to write */
|
|
next = 0; /* next element in array to be written */
|
|
rownum = 0; /* row number, relative to firstrow */
|
|
|
|
while (remain)
|
|
{
|
|
/* limit the number of pixels to process a one time to the number that
|
|
will fit in the buffer space or to the number of pixels that remain
|
|
in the current vector, which ever is smaller.
|
|
*/
|
|
ntodo = (long) minvalue(remain, maxelem);
|
|
ntodo = (long) minvalue(ntodo, (repeat - elemnum));
|
|
|
|
wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
|
|
|
|
ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
|
|
|
|
switch (tcode)
|
|
{
|
|
case (TSHORT):
|
|
if (writeraw)
|
|
{
|
|
/* write raw input bytes without conversion */
|
|
ffpi2b(fptr, ntodo, incre, &array[next], status);
|
|
}
|
|
else
|
|
{
|
|
/* convert the raw data before writing to FITS file */
|
|
ffi2fi2(&array[next], ntodo, scale, zero,
|
|
(short *) buffer, status);
|
|
ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
|
|
}
|
|
|
|
break;
|
|
|
|
case (TLONGLONG):
|
|
|
|
ffi2fi8(&array[next], ntodo, scale, zero,
|
|
(LONGLONG *) buffer, status);
|
|
ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
|
|
break;
|
|
|
|
case (TBYTE):
|
|
|
|
ffi2fi1(&array[next], ntodo, scale, zero,
|
|
(unsigned char *) buffer, status);
|
|
ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
|
|
break;
|
|
|
|
case (TLONG):
|
|
|
|
ffi2fi4(&array[next], ntodo, scale, zero,
|
|
(INT32BIT *) buffer, status);
|
|
ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
|
|
break;
|
|
|
|
case (TFLOAT):
|
|
|
|
ffi2fr4(&array[next], ntodo, scale, zero,
|
|
(float *) buffer, status);
|
|
ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
|
|
break;
|
|
|
|
case (TDOUBLE):
|
|
ffi2fr8(&array[next], ntodo, scale, zero,
|
|
(double *) buffer, status);
|
|
ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
|
|
break;
|
|
|
|
case (TSTRING): /* numerical column in an ASCII table */
|
|
|
|
if (cform[1] != 's') /* "%s" format is a string */
|
|
{
|
|
ffi2fstr(&array[next], ntodo, scale, zero, cform,
|
|
twidth, (char *) buffer, status);
|
|
|
|
|
|
if (incre == twidth) /* contiguous bytes */
|
|
ffpbyt(fptr, ntodo * twidth, buffer, status);
|
|
else
|
|
ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
|
|
status);
|
|
|
|
break;
|
|
}
|
|
/* can't write to string column, so fall thru to default: */
|
|
|
|
default: /* error trap */
|
|
snprintf(message,FLEN_ERRMSG,
|
|
"Cannot write numbers to column %d which has format %s",
|
|
colnum,tform);
|
|
ffpmsg(message);
|
|
if (hdutype == ASCII_TBL)
|
|
return(*status = BAD_ATABLE_FORMAT);
|
|
else
|
|
return(*status = BAD_BTABLE_FORMAT);
|
|
|
|
} /* End of switch block */
|
|
|
|
/*-------------------------*/
|
|
/* Check for fatal error */
|
|
/*-------------------------*/
|
|
if (*status > 0) /* test for error during previous write operation */
|
|
{
|
|
snprintf(message,FLEN_ERRMSG,
|
|
"Error writing elements %.0f thru %.0f of input data array (ffpcli).",
|
|
(double) (next+1), (double) (next+ntodo));
|
|
ffpmsg(message);
|
|
return(*status);
|
|
}
|
|
|
|
/*--------------------------------------------*/
|
|
/* increment the counters for the next loop */
|
|
/*--------------------------------------------*/
|
|
remain -= ntodo;
|
|
if (remain)
|
|
{
|
|
next += ntodo;
|
|
elemnum += ntodo;
|
|
if (elemnum == repeat) /* completed a row; start on next row */
|
|
{
|
|
elemnum = 0;
|
|
rownum++;
|
|
}
|
|
}
|
|
} /* End of main while Loop */
|
|
|
|
|
|
/*--------------------------------*/
|
|
/* check for numerical overflow */
|
|
/*--------------------------------*/
|
|
if (*status == OVERFLOW_ERR)
|
|
{
|
|
ffpmsg(
|
|
"Numerical overflow during type conversion while writing FITS data.");
|
|
*status = NUM_OVERFLOW;
|
|
}
|
|
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffpcni( fitsfile *fptr, /* I - FITS file pointer */
|
|
int colnum, /* I - number of column to write (1 = 1st col) */
|
|
LONGLONG firstrow, /* I - first row to write (1 = 1st row) */
|
|
LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */
|
|
LONGLONG nelem, /* I - number of values to write */
|
|
short *array, /* I - array of values to write */
|
|
short nulvalue, /* I - value used to flag undefined pixels */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Write an array of elements to the specified column of a table. Any input
|
|
pixels equal to the value of nulvalue will be replaced by the appropriate
|
|
null value in the output FITS file.
|
|
|
|
The input array of values will be converted to the datatype of the column
|
|
and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
|
|
*/
|
|
{
|
|
tcolumn *colptr;
|
|
LONGLONG ngood = 0, nbad = 0, ii;
|
|
LONGLONG repeat, first, fstelm, fstrow;
|
|
int tcode, overflow = 0;
|
|
|
|
if (*status > 0)
|
|
return(*status);
|
|
|
|
/* reset position to the correct HDU if necessary */
|
|
if (fptr->HDUposition != (fptr->Fptr)->curhdu)
|
|
{
|
|
ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
|
|
}
|
|
else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
|
|
{
|
|
if ( ffrdef(fptr, status) > 0) /* rescan header */
|
|
return(*status);
|
|
}
|
|
|
|
colptr = (fptr->Fptr)->tableptr; /* point to first column */
|
|
colptr += (colnum - 1); /* offset to correct column structure */
|
|
|
|
tcode = colptr->tdatatype;
|
|
|
|
if (tcode > 0)
|
|
repeat = colptr->trepeat; /* repeat count for this column */
|
|
else
|
|
repeat = firstelem -1 + nelem; /* variable length arrays */
|
|
|
|
/* if variable length array, first write the whole input vector,
|
|
then go back and fill in the nulls */
|
|
if (tcode < 0) {
|
|
if (ffpcli(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
|
|
if (*status == NUM_OVERFLOW)
|
|
{
|
|
/* ignore overflows, which are possibly the null pixel values */
|
|
/* overflow = 1; */
|
|
*status = 0;
|
|
} else {
|
|
return(*status);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* absolute element number in the column */
|
|
first = (firstrow - 1) * repeat + firstelem;
|
|
|
|
for (ii = 0; ii < nelem; ii++)
|
|
{
|
|
if (array[ii] != nulvalue) /* is this a good pixel? */
|
|
{
|
|
if (nbad) /* write previous string of bad pixels */
|
|
{
|
|
fstelm = ii - nbad + first; /* absolute element number */
|
|
fstrow = (fstelm - 1) / repeat + 1; /* starting row number */
|
|
fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */
|
|
|
|
if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
|
|
return(*status);
|
|
|
|
nbad=0;
|
|
}
|
|
|
|
ngood = ngood +1; /* the consecutive number of good pixels */
|
|
}
|
|
else
|
|
{
|
|
if (ngood) /* write previous string of good pixels */
|
|
{
|
|
fstelm = ii - ngood + first; /* absolute element number */
|
|
fstrow = (fstelm - 1) / repeat + 1; /* starting row number */
|
|
fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */
|
|
|
|
if (tcode > 0) { /* variable length arrays have already been written */
|
|
if (ffpcli(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
|
|
status) > 0) {
|
|
if (*status == NUM_OVERFLOW)
|
|
{
|
|
overflow = 1;
|
|
*status = 0;
|
|
} else {
|
|
return(*status);
|
|
}
|
|
}
|
|
}
|
|
ngood=0;
|
|
}
|
|
|
|
nbad = nbad +1; /* the consecutive number of bad pixels */
|
|
}
|
|
}
|
|
|
|
/* finished loop; now just write the last set of pixels */
|
|
|
|
if (ngood) /* write last string of good pixels */
|
|
{
|
|
fstelm = ii - ngood + first; /* absolute element number */
|
|
fstrow = (fstelm - 1) / repeat + 1; /* starting row number */
|
|
fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */
|
|
|
|
if (tcode > 0) { /* variable length arrays have already been written */
|
|
ffpcli(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
|
|
}
|
|
}
|
|
else if (nbad) /* write last string of bad pixels */
|
|
{
|
|
fstelm = ii - nbad + first; /* absolute element number */
|
|
fstrow = (fstelm - 1) / repeat + 1; /* starting row number */
|
|
fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */
|
|
|
|
ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
|
|
}
|
|
|
|
if (*status <= 0) {
|
|
if (overflow) {
|
|
*status = NUM_OVERFLOW;
|
|
}
|
|
}
|
|
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffi2fi1(short *input, /* I - array of values to be converted */
|
|
long ntodo, /* I - number of elements in the array */
|
|
double scale, /* I - FITS TSCALn or BSCALE value */
|
|
double zero, /* I - FITS TZEROn or BZERO value */
|
|
unsigned char *output, /* O - output array of converted values */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Copy input to output prior to writing output to a FITS file.
|
|
Do datatype conversion and scaling if required
|
|
*/
|
|
{
|
|
long ii;
|
|
double dvalue;
|
|
|
|
if (scale == 1. && zero == 0.)
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
{
|
|
if (input[ii] < 0)
|
|
{
|
|
*status = OVERFLOW_ERR;
|
|
output[ii] = 0;
|
|
}
|
|
else if (input[ii] > UCHAR_MAX)
|
|
{
|
|
*status = OVERFLOW_ERR;
|
|
output[ii] = UCHAR_MAX;
|
|
}
|
|
else
|
|
output[ii] = (unsigned char) input[ii];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
{
|
|
dvalue = (input[ii] - zero) / scale;
|
|
|
|
if (dvalue < DUCHAR_MIN)
|
|
{
|
|
*status = OVERFLOW_ERR;
|
|
output[ii] = 0;
|
|
}
|
|
else if (dvalue > DUCHAR_MAX)
|
|
{
|
|
*status = OVERFLOW_ERR;
|
|
output[ii] = UCHAR_MAX;
|
|
}
|
|
else
|
|
output[ii] = (unsigned char) (dvalue + .5);
|
|
}
|
|
}
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffi2fi2(short *input, /* I - array of values to be converted */
|
|
long ntodo, /* I - number of elements in the array */
|
|
double scale, /* I - FITS TSCALn or BSCALE value */
|
|
double zero, /* I - FITS TZEROn or BZERO value */
|
|
short *output, /* O - output array of converted values */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Copy input to output prior to writing output to a FITS file.
|
|
Do datatype conversion and scaling if required
|
|
*/
|
|
{
|
|
long ii;
|
|
double dvalue;
|
|
|
|
if (scale == 1. && zero == 0.)
|
|
{
|
|
memcpy(output, input, ntodo * sizeof(short) );
|
|
}
|
|
else
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
{
|
|
dvalue = (input[ii] - zero) / scale;
|
|
|
|
if (dvalue < DSHRT_MIN)
|
|
{
|
|
*status = OVERFLOW_ERR;
|
|
output[ii] = SHRT_MIN;
|
|
}
|
|
else if (dvalue > DSHRT_MAX)
|
|
{
|
|
*status = OVERFLOW_ERR;
|
|
output[ii] = SHRT_MAX;
|
|
}
|
|
else
|
|
{
|
|
if (dvalue >= 0)
|
|
output[ii] = (short) (dvalue + .5);
|
|
else
|
|
output[ii] = (short) (dvalue - .5);
|
|
}
|
|
}
|
|
}
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffi2fi4(short *input, /* I - array of values to be converted */
|
|
long ntodo, /* I - number of elements in the array */
|
|
double scale, /* I - FITS TSCALn or BSCALE value */
|
|
double zero, /* I - FITS TZEROn or BZERO value */
|
|
INT32BIT *output, /* O - output array of converted values */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Copy input to output prior to writing output to a FITS file.
|
|
Do datatype conversion and scaling if required
|
|
*/
|
|
{
|
|
long ii;
|
|
double dvalue;
|
|
|
|
if (scale == 1. && zero == 0.)
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
output[ii] = (INT32BIT) input[ii]; /* just copy input to output */
|
|
}
|
|
else
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
{
|
|
dvalue = (input[ii] - zero) / scale;
|
|
|
|
if (dvalue < DINT_MIN)
|
|
{
|
|
*status = OVERFLOW_ERR;
|
|
output[ii] = INT32_MIN;
|
|
}
|
|
else if (dvalue > DINT_MAX)
|
|
{
|
|
*status = OVERFLOW_ERR;
|
|
output[ii] = INT32_MAX;
|
|
}
|
|
else
|
|
{
|
|
if (dvalue >= 0)
|
|
output[ii] = (INT32BIT) (dvalue + .5);
|
|
else
|
|
output[ii] = (INT32BIT) (dvalue - .5);
|
|
}
|
|
}
|
|
}
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffi2fi8(short *input, /* I - array of values to be converted */
|
|
long ntodo, /* I - number of elements in the array */
|
|
double scale, /* I - FITS TSCALn or BSCALE value */
|
|
double zero, /* I - FITS TZEROn or BZERO value */
|
|
LONGLONG *output, /* O - output array of converted values */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Copy input to output prior to writing output to a FITS file.
|
|
Do datatype conversion and scaling if required
|
|
*/
|
|
{
|
|
long ii;
|
|
double dvalue;
|
|
|
|
if (scale == 1. && zero == 9223372036854775808.)
|
|
{
|
|
/* Writing to unsigned long long column. Input values must not be negative */
|
|
/* Instead of subtracting 9223372036854775808, it is more efficient */
|
|
/* and more precise to just flip the sign bit with the XOR operator */
|
|
|
|
for (ii = 0; ii < ntodo; ii++) {
|
|
if (input[ii] < 0) {
|
|
*status = OVERFLOW_ERR;
|
|
output[ii] = LONGLONG_MIN;
|
|
} else {
|
|
output[ii] = ((LONGLONG) input[ii]) ^ 0x8000000000000000;
|
|
}
|
|
}
|
|
}
|
|
else if (scale == 1. && zero == 0.)
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
output[ii] = input[ii];
|
|
}
|
|
else
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
{
|
|
dvalue = (input[ii] - zero) / scale;
|
|
|
|
if (dvalue < DLONGLONG_MIN)
|
|
{
|
|
*status = OVERFLOW_ERR;
|
|
output[ii] = LONGLONG_MIN;
|
|
}
|
|
else if (dvalue > DLONGLONG_MAX)
|
|
{
|
|
*status = OVERFLOW_ERR;
|
|
output[ii] = LONGLONG_MAX;
|
|
}
|
|
else
|
|
{
|
|
if (dvalue >= 0)
|
|
output[ii] = (LONGLONG) (dvalue + .5);
|
|
else
|
|
output[ii] = (LONGLONG) (dvalue - .5);
|
|
}
|
|
}
|
|
}
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffi2fr4(short *input, /* I - array of values to be converted */
|
|
long ntodo, /* I - number of elements in the array */
|
|
double scale, /* I - FITS TSCALn or BSCALE value */
|
|
double zero, /* I - FITS TZEROn or BZERO value */
|
|
float *output, /* O - output array of converted values */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Copy input to output prior to writing output to a FITS file.
|
|
Do datatype conversion and scaling if required.
|
|
*/
|
|
{
|
|
long ii;
|
|
|
|
if (scale == 1. && zero == 0.)
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
output[ii] = (float) input[ii];
|
|
}
|
|
else
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
output[ii] = (float) ((input[ii] - zero) / scale);
|
|
}
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffi2fr8(short *input, /* I - array of values to be converted */
|
|
long ntodo, /* I - number of elements in the array */
|
|
double scale, /* I - FITS TSCALn or BSCALE value */
|
|
double zero, /* I - FITS TZEROn or BZERO value */
|
|
double *output, /* O - output array of converted values */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Copy input to output prior to writing output to a FITS file.
|
|
Do datatype conversion and scaling if required.
|
|
*/
|
|
{
|
|
long ii;
|
|
|
|
if (scale == 1. && zero == 0.)
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
output[ii] = (double) input[ii];
|
|
}
|
|
else
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
output[ii] = (input[ii] - zero) / scale;
|
|
}
|
|
return(*status);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ffi2fstr(short *input, /* I - array of values to be converted */
|
|
long ntodo, /* I - number of elements in the array */
|
|
double scale, /* I - FITS TSCALn or BSCALE value */
|
|
double zero, /* I - FITS TZEROn or BZERO value */
|
|
char *cform, /* I - format for output string values */
|
|
long twidth, /* I - width of each field, in chars */
|
|
char *output, /* O - output array of converted values */
|
|
int *status) /* IO - error status */
|
|
/*
|
|
Copy input to output prior to writing output to a FITS file.
|
|
Do scaling if required.
|
|
*/
|
|
{
|
|
long ii;
|
|
double dvalue;
|
|
char *cptr;
|
|
|
|
cptr = output;
|
|
|
|
if (scale == 1. && zero == 0.)
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
{
|
|
sprintf(output, cform, (double) input[ii]);
|
|
output += twidth;
|
|
|
|
if (*output) /* if this char != \0, then overflow occurred */
|
|
*status = OVERFLOW_ERR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (ii = 0; ii < ntodo; ii++)
|
|
{
|
|
dvalue = (input[ii] - zero) / scale;
|
|
sprintf(output, cform, dvalue);
|
|
output += twidth;
|
|
|
|
if (*output) /* if this char != \0, then overflow occurred */
|
|
*status = OVERFLOW_ERR;
|
|
}
|
|
}
|
|
|
|
/* replace any commas with periods (e.g., in French locale) */
|
|
while ((cptr = strchr(cptr, ','))) *cptr = '.';
|
|
|
|
return(*status);
|
|
}
|