1
/* This file, getcols.c, contains routines that read data elements from */
2
/* a FITS image or table, with a character string datatype. */
4
/* The FITSIO software was written by William Pence at the High Energy */
5
/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */
6
/* Goddard Space Flight Center. */
10
/* stddef.h is apparently needed to define size_t */
14
/*--------------------------------------------------------------------------*/
15
int ffgcvs( fitsfile *fptr, /* I - FITS file pointer */
16
int colnum, /* I - number of column to read (1 = 1st col) */
17
LONGLONG firstrow, /* I - first row to read (1 = 1st row) */
18
LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
19
LONGLONG nelem, /* I - number of strings to read */
20
char *nulval, /* I - string for null pixels */
21
char **array, /* O - array of values that are read */
22
int *anynul, /* O - set to 1 if any values are null; else 0 */
23
int *status) /* IO - error status */
25
Read an array of string values from a column in the current FITS HDU.
26
Any undefined pixels will be set equal to the value of 'nulval' unless
27
nulval = null in which case no checks for undefined pixels will be made.
32
ffgcls(fptr, colnum, firstrow, firstelem, nelem, 1, nulval,
33
array, cdummy, anynul, status);
36
/*--------------------------------------------------------------------------*/
37
int ffgcfs( fitsfile *fptr, /* I - FITS file pointer */
38
int colnum, /* I - number of column to read (1 = 1st col) */
39
LONGLONG firstrow, /* I - first row to read (1 = 1st row) */
40
LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
41
LONGLONG nelem, /* I - number of strings to read */
42
char **array, /* O - array of values that are read */
43
char *nularray, /* O - array of flags = 1 if nultyp = 2 */
44
int *anynul, /* O - set to 1 if any values are null; else 0 */
45
int *status) /* IO - error status */
47
Read an array of string values from a column in the current FITS HDU.
48
Nularray will be set = 1 if the corresponding array pixel is undefined,
49
otherwise nularray will = 0.
54
ffgcls(fptr, colnum, firstrow, firstelem, nelem, 2, dummy,
55
array, nularray, anynul, status);
58
/*--------------------------------------------------------------------------*/
59
int ffgcls( fitsfile *fptr, /* I - FITS file pointer */
60
int colnum, /* I - number of column to read (1 = 1st col) */
61
LONGLONG firstrow, /* I - first row to read (1 = 1st row) */
62
LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
63
LONGLONG nelem, /* I - number of strings to read */
64
int nultyp, /* I - null value handling code: */
65
/* 1: set undefined pixels = nulval */
66
/* 2: set nularray=1 for undefined pixels */
67
char *nulval, /* I - value for null pixels if nultyp = 1 */
68
char **array, /* O - array of values that are read */
69
char *nularray, /* O - array of flags = 1 if nultyp = 2 */
70
int *anynul, /* O - set to 1 if any values are null; else 0 */
71
int *status) /* IO - error status */
73
Read an array of string values from a column in the current FITS HDU.
74
Returns a formated string value, regardless of the datatype of the column
77
int tcode, hdutype, tstatus, scaled, intcol, dwidth, nulwidth, ll, dlen;
80
char message[FLEN_ERRMSG], *carray, keyname[FLEN_KEYWORD];
81
char cform[20], dispfmt[20], tmpstr[400], *flgarray, tmpnull[80];
82
unsigned char byteval;
84
double *darray, tscale = 1.0;
87
if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */
90
/* reset position to the correct HDU if necessary */
91
if (fptr->HDUposition != (fptr->Fptr)->curhdu)
92
ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
94
/* rescan header if data structure is undefined */
95
else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
96
if ( ffrdef(fptr, status) > 0)
99
if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
101
sprintf(message, "Specified column number is out of range: %d",
104
return(*status = BAD_COL_NUM);
107
colptr = (fptr->Fptr)->tableptr; /* point to first column */
108
colptr += (colnum - 1); /* offset to correct column structure */
109
tcode = abs(colptr->tdatatype);
111
if (tcode == TSTRING)
113
/* simply call the string column reading routine */
114
ffgcls2(fptr, colnum, firstrow, firstelem, nelem, nultyp, nulval,
115
array, nularray, anynul, status);
117
else if (tcode == TLOGICAL)
119
/* allocate memory for the array of logical values */
120
carray = (char *) malloc((size_t) nelem);
122
/* call the logical column reading routine */
123
ffgcll(fptr, colnum, firstrow, firstelem, nelem, nultyp, *nulval,
124
carray, nularray, anynul, status);
128
/* convert logical values to "T", "F", or "N" (Null) */
129
for (ii = 0; ii < nelem; ii++)
132
strcpy(array[ii], "T");
133
else if (carray[ii] == 0)
134
strcpy(array[ii], "F");
135
else /* undefined values = 2 */
136
strcpy(array[ii],"N");
140
free(carray); /* free the memory */
142
else if (tcode == TCOMPLEX)
144
/* allocate memory for the array of double values */
145
earray = (float *) calloc((size_t) (nelem * 2), sizeof(float) );
147
ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
148
1, 1, FLOATNULLVALUE, earray, nularray, anynul, status);
153
/* determine the format for the output strings */
155
ffgcdw(fptr, colnum, &dwidth, status);
156
dwidth = (dwidth - 3) / 2;
158
/* use the TDISPn keyword if it exists */
159
ffkeyn("TDISP", colnum, keyname, status);
163
if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
165
/* convert the Fortran style format to a C style format */
166
ffcdsp(dispfmt, cform);
170
strcpy(cform, "%14.6E");
172
/* write the formated string for each value: "(real,imag)" */
174
for (ii = 0; ii < nelem; ii++)
176
strcpy(array[ii], "(");
178
/* test for null value */
179
if (earray[jj] == FLOATNULLVALUE)
181
strcpy(tmpstr, "NULL");
186
sprintf(tmpstr, cform, earray[jj]);
188
strncat(array[ii], tmpstr, dwidth);
189
strcat(array[ii], ",");
192
/* test for null value */
193
if (earray[jj] == FLOATNULLVALUE)
195
strcpy(tmpstr, "NULL");
200
sprintf(tmpstr, cform, earray[jj]);
202
strncat(array[ii], tmpstr, dwidth);
203
strcat(array[ii], ")");
208
free(earray); /* free the memory */
210
else if (tcode == TDBLCOMPLEX)
212
/* allocate memory for the array of double values */
213
darray = (double *) calloc((size_t) (nelem * 2), sizeof(double) );
215
ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
216
1, 1, DOUBLENULLVALUE, darray, nularray, anynul, status);
220
/* determine the format for the output strings */
222
ffgcdw(fptr, colnum, &dwidth, status);
223
dwidth = (dwidth - 3) / 2;
225
/* use the TDISPn keyword if it exists */
226
ffkeyn("TDISP", colnum, keyname, status);
230
if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
232
/* convert the Fortran style format to a C style format */
233
ffcdsp(dispfmt, cform);
237
strcpy(cform, "%23.15E");
239
/* write the formated string for each value: "(real,imag)" */
241
for (ii = 0; ii < nelem; ii++)
243
strcpy(array[ii], "(");
245
/* test for null value */
246
if (darray[jj] == DOUBLENULLVALUE)
248
strcpy(tmpstr, "NULL");
253
sprintf(tmpstr, cform, darray[jj]);
255
strncat(array[ii], tmpstr, dwidth);
256
strcat(array[ii], ",");
259
/* test for null value */
260
if (darray[jj] == DOUBLENULLVALUE)
262
strcpy(tmpstr, "NULL");
267
sprintf(tmpstr, cform, darray[jj]);
269
strncat(array[ii], tmpstr, dwidth);
270
strcat(array[ii], ")");
275
free(darray); /* free the memory */
277
else if (tcode == TLONGLONG)
279
/* allocate memory for the array of LONGLONG values */
280
llarray = (LONGLONG *) calloc((size_t) nelem, sizeof(LONGLONG) );
281
flgarray = (char *) calloc((size_t) nelem, sizeof(char) );
282
dwidth = 20; /* max width of displayed long long integer value */
284
if (ffgcfjj(fptr, colnum, firstrow, firstelem, nelem,
285
llarray, flgarray, anynul, status) > 0)
292
/* write the formated string for each value */
294
strcpy(tmpnull, nulval);
295
nulwidth = strlen(nulval);
297
strcpy(tmpnull, " ");
301
for (ii = 0; ii < nelem; ii++)
306
if (dwidth < nulwidth)
307
strncat(array[ii], tmpnull, dwidth);
309
sprintf(array[ii],"%*s",dwidth,tmpnull);
317
#if defined(_MSC_VER)
318
/* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */
319
sprintf(tmpstr, "%20I64d", llarray[ii]);
320
#elif (USE_LL_SUFFIX == 1)
321
sprintf(tmpstr, "%20lld", llarray[ii]);
323
sprintf(tmpstr, "%20ld", llarray[ii]);
326
strncat(array[ii], tmpstr, 20);
331
free(llarray); /* free the memory */
336
/* allocate memory for the array of double values */
337
darray = (double *) calloc((size_t) nelem, sizeof(double) );
339
/* read all other numeric type columns as doubles */
340
if (ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, nultyp,
341
DOUBLENULLVALUE, darray, nularray, anynul, status) > 0)
347
/* determine the format for the output strings */
349
ffgcdw(fptr, colnum, &dwidth, status);
351
/* check if column is scaled */
352
ffkeyn("TSCAL", colnum, keyname, status);
355
if (ffgkyd(fptr, keyname, &tscale, NULL, &tstatus) == 0)
358
scaled = 1; /* yes, this is a scaled column */
362
if (tcode <= TLONG && !scaled)
363
intcol = 1; /* this is an unscaled integer column */
365
/* use the TDISPn keyword if it exists */
366
ffkeyn("TDISP", colnum, keyname, status);
370
if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
372
/* convert the Fortran style TDISPn to a C style format */
373
ffcdsp(dispfmt, cform);
378
/* no TDISPn keyword; use TFORMn instead */
380
ffkeyn("TFORM", colnum, keyname, status);
381
ffgkys(fptr, keyname, dispfmt, NULL, status);
383
if (scaled && tcode <= TSHORT)
385
/* scaled short integer column == float */
386
strcpy(cform, "%#14.6G");
388
else if (scaled && tcode == TLONG)
390
/* scaled long integer column == double */
391
strcpy(cform, "%#23.15G");
395
ffghdt(fptr, &hdutype, status);
396
if (hdutype == ASCII_TBL)
398
/* convert the Fortran style TFORMn to a C style format */
399
ffcdsp(dispfmt, cform);
403
/* this is a binary table, need to convert the format */
404
if (tcode == TBIT) { /* 'X' */
405
strcpy(cform, "%4d");
406
} else if (tcode == TBYTE) { /* 'B' */
407
strcpy(cform, "%4d");
408
} else if (tcode == TSHORT) { /* 'I' */
409
strcpy(cform, "%6d");
410
} else if (tcode == TLONG) { /* 'J' */
411
strcpy(cform, "%11.0f");
412
intcol = 0; /* needed to support unsigned int */
413
} else if (tcode == TFLOAT) { /* 'E' */
414
strcpy(cform, "%#14.6G");
415
} else if (tcode == TDOUBLE) { /* 'D' */
416
strcpy(cform, "%#23.15G");
423
strcpy(tmpnull, nulval);
424
nulwidth = strlen(nulval);
426
strcpy(tmpnull, " ");
430
/* write the formated string for each value */
431
for (ii = 0; ii < nelem; ii++)
435
byteval = (char) darray[ii];
437
for (ll=0; ll < 8; ll++)
439
if ( ((unsigned char) (byteval << ll)) >> 7 )
440
*(array[ii] + ll) = '1';
442
*(array[ii] + ll) = '0';
444
*(array[ii] + 8) = '\0';
446
/* test for null value */
447
else if ( (nultyp == 1 && darray[ii] == DOUBLENULLVALUE) ||
448
(nultyp == 2 && nularray[ii]) )
451
if (dwidth < nulwidth)
452
strncat(array[ii], tmpnull, dwidth);
454
sprintf(array[ii],"%*s",dwidth,tmpnull);
459
sprintf(tmpstr, cform, (int) darray[ii]);
461
sprintf(tmpstr, cform, darray[ii]);
463
/* fill field with '*' if number is too wide */
464
dlen = strlen(tmpstr);
466
memset(tmpstr, '*', dwidth);
470
strncat(array[ii], tmpstr, dwidth);
474
free(darray); /* free the memory */
478
/*--------------------------------------------------------------------------*/
479
int ffgcdw( fitsfile *fptr, /* I - FITS file pointer */
480
int colnum, /* I - number of column (1 = 1st col) */
481
int *width, /* O - display width */
482
int *status) /* IO - error status */
484
Get Column Display Width.
489
char message[FLEN_ERRMSG], keyname[FLEN_KEYWORD], dispfmt[20];
490
int tcode, hdutype, tstatus, scaled;
493
if (*status > 0) /* inherit input status value if > 0 */
496
if (fptr->HDUposition != (fptr->Fptr)->curhdu)
497
ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
499
if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
501
sprintf(message, "Specified column number is out of range: %d",
504
return(*status = BAD_COL_NUM);
507
colptr = (fptr->Fptr)->tableptr; /* point to first column */
508
colptr += (colnum - 1); /* offset to correct column structure */
509
tcode = abs(colptr->tdatatype);
511
/* use the TDISPn keyword if it exists */
512
ffkeyn("TDISP", colnum, keyname, status);
516
if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
518
/* parse TDISPn get the display width */
520
while(*cptr == ' ') /* skip leading blanks */
523
if (*cptr == 'A' || *cptr == 'a' ||
524
*cptr == 'I' || *cptr == 'i' ||
525
*cptr == 'O' || *cptr == 'o' ||
526
*cptr == 'Z' || *cptr == 'z' ||
527
*cptr == 'F' || *cptr == 'f' ||
528
*cptr == 'E' || *cptr == 'e' ||
529
*cptr == 'D' || *cptr == 'd' ||
530
*cptr == 'G' || *cptr == 'g')
533
while(!isdigit((int) *cptr) && *cptr != '\0') /* find 1st digit */
537
if (tcode >= TCOMPLEX)
538
*width = (2 * (*width)) + 3;
544
/* no valid TDISPn keyword; use TFORMn instead */
546
ffkeyn("TFORM", colnum, keyname, status);
547
ffgkys(fptr, keyname, dispfmt, NULL, status);
549
/* check if column is scaled */
550
ffkeyn("TSCAL", colnum, keyname, status);
554
if (ffgkyd(fptr, keyname, &tscale, NULL, &tstatus) == 0)
557
scaled = 1; /* yes, this is a scaled column */
560
if (scaled && tcode <= TSHORT)
562
/* scaled short integer col == float; default format is 14.6G */
565
else if (scaled && tcode == TLONG)
567
/* scaled long integer col == double; default format is 23.15G */
572
ffghdt(fptr, &hdutype, status); /* get type of table */
573
if (hdutype == ASCII_TBL)
575
/* parse TFORMn get the display width */
577
while(!isdigit((int) *cptr) && *cptr != '\0') /* find 1st digit */
584
/* this is a binary table */
585
if (tcode == TBIT) /* 'X' */
587
else if (tcode == TBYTE) /* 'B' */
589
else if (tcode == TSHORT) /* 'I' */
591
else if (tcode == TLONG) /* 'J' */
593
else if (tcode == TLONGLONG) /* 'K' */
595
else if (tcode == TFLOAT) /* 'E' */
597
else if (tcode == TDOUBLE) /* 'D' */
599
else if (tcode == TCOMPLEX) /* 'C' */
601
else if (tcode == TDBLCOMPLEX) /* 'M' */
603
else if (tcode == TLOGICAL) /* 'L' */
605
else if (tcode == TSTRING) /* 'A' */
608
while(!isdigit((int) *cptr) && *cptr != '\0')
614
*width = 1; /* default is at least 1 column */
621
/*--------------------------------------------------------------------------*/
622
int ffgcls2 ( fitsfile *fptr, /* I - FITS file pointer */
623
int colnum, /* I - number of column to read (1 = 1st col) */
624
LONGLONG firstrow, /* I - first row to read (1 = 1st row) */
625
LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
626
LONGLONG nelem, /* I - number of strings to read */
627
int nultyp, /* I - null value handling code: */
628
/* 1: set undefined pixels = nulval */
629
/* 2: set nularray=1 for undefined pixels */
630
char *nulval, /* I - value for null pixels if nultyp = 1 */
631
char **array, /* O - array of values that are read */
632
char *nularray, /* O - array of flags = 1 if nultyp = 2 */
633
int *anynul, /* O - set to 1 if any values are null; else 0 */
634
int *status) /* IO - error status */
636
Read an array of string values from a column in the current FITS HDU.
641
int tcode, maxelem, hdutype, nulcheck;
644
LONGLONG repeat, startpos, elemnum, readptr, tnull, rowlen, rownum, remain, next;
647
char message[FLEN_ERRMSG];
648
char snull[20]; /* the FITS null value */
651
double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
652
char *buffer, *arrayptr;
654
if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */
657
if (fptr->HDUposition != (fptr->Fptr)->curhdu)
658
ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
664
memset(nularray, 0, (size_t) nelem); /* initialize nullarray */
666
/*---------------------------------------------------*/
667
/* Check input and get parameters about the column: */
668
/*---------------------------------------------------*/
669
if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
671
sprintf(message, "Specified column number is out of range: %d",
674
return(*status = BAD_COL_NUM);
677
colptr = (fptr->Fptr)->tableptr; /* point to first column */
678
colptr += (colnum - 1); /* offset to correct column structure */
679
tcode = colptr->tdatatype;
681
if (tcode == -TSTRING) /* variable length column in a binary table? */
683
/* only read a single string; ignore value of firstelem */
685
if (ffgcprll( fptr, colnum, firstrow, 1, 1, 0, &scale, &zero,
686
tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre,
687
&repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
691
twidth = (long) repeat;
693
else if (tcode == TSTRING)
695
if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
696
tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre,
697
&repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
700
/* if string length is greater than a FITS block (2880 char) then must */
701
/* only read 1 string at a time, to force reading by ffgbyt instead of */
702
/* ffgbytoff (ffgbytoff can't handle this case) */
703
if (twidth > IOBUFLEN) {
712
return(*status = NOT_ASCII_COL);
714
nullen = strlen(snull); /* length of the undefined pixel string */
718
/*------------------------------------------------------------------*/
719
/* Decide whether to check for null values in the input FITS file: */
720
/*------------------------------------------------------------------*/
721
nulcheck = nultyp; /* by default check for null values in the FITS file */
723
if (nultyp == 1 && nulval == 0)
724
nulcheck = 0; /* calling routine does not want to check for nulls */
726
else if (nultyp == 1 && nulval && nulval[0] == 0)
727
nulcheck = 0; /* calling routine does not want to check for nulls */
729
else if (snull[0] == ASCII_NULL_UNDEFINED)
730
nulcheck = 0; /* null value string in ASCII table not defined */
732
else if (nullen > twidth)
733
nulcheck = 0; /* null value string is longer than width of column */
734
/* thus impossible for any column elements to = null */
736
/*---------------------------------------------------------------------*/
737
/* Now read the strings one at a time from the FITS column. */
738
/*---------------------------------------------------------------------*/
739
next = 0; /* next element in array to be read */
740
rownum = 0; /* row number, relative to firstrow */
744
/* limit the number of pixels to process at one time to the number that
745
will fit in the buffer space or to the number of pixels that remain
746
in the current vector, which ever is smaller.
748
ntodo = (long) minvalue(remain, maxelem);
749
ntodo = (long) minvalue(ntodo, (repeat - elemnum));
751
readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
752
ffmbyt(fptr, readptr, REPORT_EOF, status); /* move to read position */
754
/* read the array of strings from the FITS file into the buffer */
757
ffgbyt(fptr, ntodo * twidth, cbuff, status);
759
ffgbytoff(fptr, twidth, ntodo, incre - twidth, cbuff, status);
761
/* copy from the buffer into the user's array of strings */
762
/* work backwards from last char of last string to 1st char of 1st */
764
buffer = ((char *) cbuff) + (ntodo * twidth) - 1;
766
for (ii = (long) (next + ntodo - 1); ii >= next; ii--)
768
arrayptr = array[ii] + twidth - 1;
770
for (jj = twidth - 1; jj > 0; jj--) /* ignore trailing blanks */
780
*(arrayptr + 1) = 0; /* write the string terminator */
782
for (; jj >= 0; jj--) /* copy the string itself */
789
/* check if null value is defined, and if the */
790
/* column string is identical to the null string */
791
if (nulcheck && !strncmp(snull, array[ii], nullen) )
793
*anynul = 1; /* this is a null value */
797
strcpy(array[ii], nulval);
799
strcpy(array[ii], " ");
806
if (*status > 0) /* test for error during previous read operation */
808
dtemp = (double) next;
810
"Error reading elements %.0f thru %.0f of data array (ffpcls).",
811
dtemp+1., dtemp+ntodo);
817
/*--------------------------------------------*/
818
/* increment the counters for the next loop */
819
/*--------------------------------------------*/
825
if (elemnum == repeat) /* completed a row; start on next row */
831
} /* End of main while Loop */