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