1 /* This file, putcoll.c, contains routines that write data elements to */
2 /* a FITS image or table, with logical datatype. */
3
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. */
7
8 #include <string.h>
9 #include <stdlib.h>
10 #include "fitsio2.h"
11
12 /*--------------------------------------------------------------------------*/
ffpcll(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,char * array,int * status)13 int ffpcll( fitsfile *fptr, /* I - FITS file pointer */
14 int colnum, /* I - number of column to write (1 = 1st col) */
15 LONGLONG firstrow, /* I - first row to write (1 = 1st row) */
16 LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */
17 LONGLONG nelem, /* I - number of values to write */
18 char *array, /* I - array of values to write */
19 int *status) /* IO - error status */
20 /*
21 Write an array of logical values to a column in the current FITS HDU.
22 */
23 {
24 int tcode, maxelem, hdutype;
25 long twidth, incre;
26 LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
27 double scale, zero;
28 char tform[20], ctrue = 'T', cfalse = 'F';
29 char message[FLEN_ERRMSG];
30 char snull[20]; /* the FITS null value */
31
32 if (*status > 0) /* inherit input status value if > 0 */
33 return(*status);
34
35 /*---------------------------------------------------*/
36 /* Check input and get parameters about the column: */
37 /*---------------------------------------------------*/
38 if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
39 tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre,
40 &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
41 return(*status);
42
43 if (tcode != TLOGICAL)
44 return(*status = NOT_LOGICAL_COL);
45
46 /*---------------------------------------------------------------------*/
47 /* Now write the logical values one at a time to the FITS column. */
48 /*---------------------------------------------------------------------*/
49 remain = nelem; /* remaining number of values to write */
50 next = 0; /* next element in array to be written */
51 rownum = 0; /* row number, relative to firstrow */
52
53 while (remain)
54 {
55 wrtptr = startpos + (rowlen * rownum) + (elemnum * incre);
56
57 ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
58
59 if (array[next])
60 ffpbyt(fptr, 1, &ctrue, status);
61 else
62 ffpbyt(fptr, 1, &cfalse, status);
63
64 if (*status > 0) /* test for error during previous write operation */
65 {
66 snprintf(message,FLEN_ERRMSG,
67 "Error writing element %.0f of input array of logicals (ffpcll).",
68 (double) (next+1));
69 ffpmsg(message);
70 return(*status);
71 }
72
73 /*--------------------------------------------*/
74 /* increment the counters for the next loop */
75 /*--------------------------------------------*/
76 remain--;
77 if (remain)
78 {
79 next++;
80 elemnum++;
81 if (elemnum == repeat) /* completed a row; start on next row */
82 {
83 elemnum = 0;
84 rownum++;
85 }
86 }
87
88 } /* End of main while Loop */
89
90 return(*status);
91 }
92 /*--------------------------------------------------------------------------*/
ffpcnl(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,char * array,char nulvalue,int * status)93 int ffpcnl( fitsfile *fptr, /* I - FITS file pointer */
94 int colnum, /* I - number of column to write (1 = 1st col) */
95 LONGLONG firstrow, /* I - first row to write (1 = 1st row) */
96 LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */
97 LONGLONG nelem, /* I - number of values to write */
98 char *array, /* I - array of values to write */
99 char nulvalue, /* I - array flagging undefined pixels if true */
100 int *status) /* IO - error status */
101 /*
102 Write an array of elements to the specified column of a table. Any input
103 pixels flagged as null will be replaced by the appropriate
104 null value in the output FITS file.
105 */
106 {
107 tcolumn *colptr;
108 LONGLONG ngood = 0, nbad = 0, ii;
109 LONGLONG repeat, first, fstelm, fstrow;
110 int tcode;
111
112 if (*status > 0)
113 return(*status);
114
115 /* reset position to the correct HDU if necessary */
116 if (fptr->HDUposition != (fptr->Fptr)->curhdu)
117 {
118 ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
119 }
120 else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
121 {
122 if ( ffrdef(fptr, status) > 0) /* rescan header */
123 return(*status);
124 }
125
126 colptr = (fptr->Fptr)->tableptr; /* point to first column */
127 colptr += (colnum - 1); /* offset to correct column structure */
128
129 tcode = colptr->tdatatype;
130
131 if (tcode > 0)
132 repeat = colptr->trepeat; /* repeat count for this column */
133 else
134 repeat = firstelem -1 + nelem; /* variable length arrays */
135
136 /* first write the whole input vector, then go back and fill in the nulls */
137 if (ffpcll(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0)
138 return(*status);
139
140 /* absolute element number in the column */
141 first = (firstrow - 1) * repeat + firstelem;
142
143 for (ii = 0; ii < nelem; ii++)
144 {
145 if (array[ii] != nulvalue) /* is this a good pixel? */
146 {
147 if (nbad) /* write previous string of bad pixels */
148 {
149 fstelm = ii - nbad + first; /* absolute element number */
150 fstrow = (fstelm - 1) / repeat + 1; /* starting row number */
151 fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */
152
153 if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
154 return(*status);
155
156 nbad=0;
157 }
158
159 ngood = ngood +1; /* the consecutive number of good pixels */
160 }
161 else
162 {
163 if (ngood) /* write previous string of good pixels */
164 {
165 fstelm = ii - ngood + first; /* absolute element number */
166 fstrow = (fstelm - 1) / repeat + 1; /* starting row number */
167 fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */
168
169 /* good values have already been written
170 if (ffpcll(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
171 status) > 0)
172 return(*status);
173 */
174 ngood=0;
175 }
176
177 nbad = nbad +1; /* the consecutive number of bad pixels */
178 }
179 }
180
181 /* finished loop; now just write the last set of pixels */
182
183 if (ngood) /* write last string of good pixels */
184 {
185 fstelm = ii - ngood + first; /* absolute element number */
186 fstrow = (fstelm - 1) / repeat + 1; /* starting row number */
187 fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */
188
189 /* these have already been written
190 ffpcll(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
191 */
192 }
193 else if (nbad) /* write last string of bad pixels */
194 {
195 fstelm = ii - nbad + first; /* absolute element number */
196 fstrow = (fstelm - 1) / repeat + 1; /* starting row number */
197 fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */
198
199 ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
200 }
201
202 return(*status);
203 }
204 /*--------------------------------------------------------------------------*/
ffpclx(fitsfile * fptr,int colnum,LONGLONG frow,long fbit,long nbit,char * larray,int * status)205 int ffpclx( fitsfile *fptr, /* I - FITS file pointer */
206 int colnum, /* I - number of column to write (1 = 1st col) */
207 LONGLONG frow, /* I - first row to write (1 = 1st row) */
208 long fbit, /* I - first bit to write (1 = 1st) */
209 long nbit, /* I - number of bits to write */
210 char *larray, /* I - array of logicals corresponding to bits */
211 int *status) /* IO - error status */
212 /*
213 write an array of logical values to a specified bit or byte
214 column of the binary table. If larray is TRUE, then the corresponding
215 bit is set to 1, otherwise it is set to 0.
216 The binary table column being written to must have datatype 'B' or 'X'.
217 */
218 {
219 LONGLONG offset, bstart, repeat, rowlen, elemnum, rstart, estart, tnull;
220 long fbyte, lbyte, nbyte, bitloc, ndone;
221 long ii, twidth, incre;
222 int tcode, descrp, maxelem, hdutype;
223 double dummyd;
224 char tform[12], snull[12];
225 unsigned char cbuff;
226 static unsigned char onbit[8] = {128, 64, 32, 16, 8, 4, 2, 1};
227 static unsigned char offbit[8] = {127, 191, 223, 239, 247, 251, 253, 254};
228 LONGLONG heapoffset, lrepeat;
229 tcolumn *colptr;
230
231 if (*status > 0) /* inherit input status value if > 0 */
232 return(*status);
233
234 /* check input parameters */
235 if (nbit < 1)
236 return(*status);
237 else if (frow < 1)
238 return(*status = BAD_ROW_NUM);
239 else if (fbit < 1)
240 return(*status = BAD_ELEM_NUM);
241
242 /* reset position to the correct HDU if necessary */
243 if (fptr->HDUposition != (fptr->Fptr)->curhdu)
244 ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
245
246 /* rescan header if data structure is undefined */
247 else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
248 if ( ffrdef(fptr, status) > 0)
249 return(*status);
250
251 fbyte = (fbit + 7) / 8;
252 lbyte = (fbit + nbit + 6) / 8;
253 nbyte = lbyte - fbyte +1;
254
255 /* Save the current heapsize; ffgcprll will increment the value if */
256 /* we are writing to a variable length column. */
257 offset = (fptr->Fptr)->heapsize;
258
259 /* call ffgcprll in case we are writing beyond the current end of */
260 /* the table; it will allocate more space and shift any following */
261 /* HDU's. Otherwise, we have little use for most of the returned */
262 /* parameters, therefore just use dummy parameters. */
263
264 if (ffgcprll( fptr, colnum, frow, fbyte, nbyte, 1, &dummyd, &dummyd,
265 tform, &twidth, &tcode, &maxelem, &bstart, &elemnum, &incre,
266 &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
267 return(*status);
268
269 bitloc = fbit - 1 - ((fbit - 1) / 8 * 8);
270 ndone = 0;
271 rstart = frow - 1;
272 estart = fbyte - 1;
273
274 colptr = (fptr->Fptr)->tableptr; /* point to first column */
275 colptr += (colnum - 1); /* offset to correct column structure */
276
277 tcode = colptr->tdatatype;
278
279 if (abs(tcode) > TBYTE)
280 return(*status = NOT_LOGICAL_COL); /* not correct datatype column */
281
282 if (tcode > 0)
283 {
284 descrp = FALSE; /* not a variable length descriptor column */
285 repeat = colptr->trepeat;
286
287 if (tcode == TBIT)
288 repeat = (repeat + 7) / 8; /* convert from bits to bytes */
289
290 if (fbyte > repeat)
291 return(*status = BAD_ELEM_NUM);
292
293 /* calc the i/o pointer location to start of sequence of pixels */
294 bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) +
295 colptr->tbcol + estart;
296 }
297 else
298 {
299 descrp = TRUE; /* a variable length descriptor column */
300 /* only bit arrays (tform = 'X') are supported for variable */
301 /* length arrays. REPEAT is the number of BITS in the array. */
302
303 repeat = fbit + nbit -1;
304
305 /* write the number of elements and the starting offset. */
306 /* Note: ffgcprll previous wrote the descripter, but with the */
307 /* wrong repeat value (gave bytes instead of bits). */
308 /* Make sure to not change the current heap offset value! */
309
310 if (tcode == -TBIT) {
311 ffgdesll(fptr, colnum, frow, &lrepeat, &heapoffset, status);
312 ffpdes( fptr, colnum, frow, (long) repeat, heapoffset, status);
313 }
314
315 /* Calc the i/o pointer location to start of sequence of pixels. */
316 /* ffgcprll has already calculated a value for bstart that */
317 /* points to the first element of the vector; we just have to */
318 /* increment it to point to the first element we want to write to. */
319 /* Note: ffgcprll also already updated the size of the heap, so we */
320 /* don't have to do that again here. */
321
322 bstart += estart;
323 }
324
325 /* move the i/o pointer to the start of the pixel sequence */
326 ffmbyt(fptr, bstart, IGNORE_EOF, status);
327
328 /* read the next byte (we may only be modifying some of the bits) */
329 while (1)
330 {
331 if (ffgbyt(fptr, 1, &cbuff, status) == END_OF_FILE)
332 {
333 /* hit end of file trying to read the byte, so just set byte = 0 */
334 *status = 0;
335 cbuff = 0;
336 }
337
338 /* move back, to be able to overwrite the byte */
339 ffmbyt(fptr, bstart, IGNORE_EOF, status);
340
341 for (ii = bitloc; (ii < 8) && (ndone < nbit); ii++, ndone++)
342 {
343 if(larray[ndone])
344 cbuff = cbuff | onbit[ii];
345 else
346 cbuff = cbuff & offbit[ii];
347 }
348
349 ffpbyt(fptr, 1, &cbuff, status); /* write the modified byte */
350 if (ndone == nbit) /* finished all the bits */
351 return(*status);
352
353 /* not done, so get the next byte */
354 bstart++;
355 if (!descrp)
356 {
357 estart++;
358 if (estart == repeat)
359 {
360 /* move the i/o pointer to the next row of pixels */
361 estart = 0;
362 rstart = rstart + 1;
363 bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) +
364 colptr->tbcol;
365
366 ffmbyt(fptr, bstart, IGNORE_EOF, status);
367 }
368 }
369 bitloc = 0;
370 }
371 }
372
373