1 /* This file, putcolu.c, contains routines that write data elements to */
2 /* a FITS image or table. Writes null values. */
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 /*--------------------------------------------------------------------------*/
ffppru(fitsfile * fptr,long group,LONGLONG firstelem,LONGLONG nelem,int * status)13 int ffppru( fitsfile *fptr, /* I - FITS file pointer */
14 long group, /* I - group to write(1 = 1st group) */
15 LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */
16 LONGLONG nelem, /* I - number of values to write */
17 int *status) /* IO - error status */
18 /*
19 Write null values to the primary array.
20
21 */
22 {
23 long row;
24
25 /*
26 the primary array is represented as a binary table:
27 each group of the primary array is a row in the table,
28 where the first column contains the group parameters
29 and the second column contains the image itself.
30 */
31
32 if (fits_is_compressed_image(fptr, status))
33 {
34 /* this is a compressed image in a binary table */
35
36 ffpmsg("writing to compressed image is not supported");
37
38 return(*status = DATA_COMPRESSION_ERR);
39 }
40
41 row=maxvalue(1,group);
42
43 ffpclu(fptr, 2, row, firstelem, nelem, status);
44 return(*status);
45 }
46 /*--------------------------------------------------------------------------*/
ffpprn(fitsfile * fptr,LONGLONG firstelem,LONGLONG nelem,int * status)47 int ffpprn( fitsfile *fptr, /* I - FITS file pointer */
48 LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */
49 LONGLONG nelem, /* I - number of values to write */
50 int *status) /* IO - error status */
51 /*
52 Write null values to the primary array. (Doesn't support groups).
53
54 */
55 {
56 long row = 1;
57
58 /*
59 the primary array is represented as a binary table:
60 each group of the primary array is a row in the table,
61 where the first column contains the group parameters
62 and the second column contains the image itself.
63 */
64
65 if (fits_is_compressed_image(fptr, status))
66 {
67 /* this is a compressed image in a binary table */
68
69 ffpmsg("writing to compressed image is not supported");
70
71 return(*status = DATA_COMPRESSION_ERR);
72 }
73
74 ffpclu(fptr, 2, row, firstelem, nelem, status);
75 return(*status);
76 }
77 /*--------------------------------------------------------------------------*/
ffpclu(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelempar,int * status)78 int ffpclu( fitsfile *fptr, /* I - FITS file pointer */
79 int colnum, /* I - number of column to write (1 = 1st col) */
80 LONGLONG firstrow, /* I - first row to write (1 = 1st row) */
81 LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */
82 LONGLONG nelempar, /* I - number of values to write */
83 int *status) /* IO - error status */
84 /*
85 Set elements of a table column to the appropriate null value for the column
86 The column number may refer to a real column in an ASCII or binary table,
87 or it may refer to a virtual column in a 1 or more grouped FITS primary
88 array. FITSIO treats a primary array as a binary table
89 with 2 vector columns: the first column contains the group parameters (often
90 with length = 0) and the second column contains the array of image pixels.
91 Each row of the table represents a group in the case of multigroup FITS
92 images.
93
94 This routine support COMPLEX and DOUBLE COMPLEX binary table columns, and
95 sets both the real and imaginary components of the element to a NaN.
96 */
97 {
98 int tcode, maxelem, hdutype, writemode = 2, leng;
99 short i2null;
100 INT32BIT i4null;
101 long twidth, incre;
102 LONGLONG ii;
103 LONGLONG largeelem, nelem, tnull, i8null;
104 LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, ntodo;
105 double scale, zero;
106 unsigned char i1null, lognul = 0;
107 char tform[20], *cstring = 0;
108 char message[FLEN_ERRMSG];
109 char snull[20]; /* the FITS null value */
110 long jbuff[2] = { -1, -1}; /* all bits set is equivalent to a NaN */
111 size_t buffsize;
112
113 if (*status > 0) /* inherit input status value if > 0 */
114 return(*status);
115
116 nelem = nelempar;
117
118 largeelem = firstelem;
119
120 /*---------------------------------------------------*/
121 /* Check input and get parameters about the column: */
122 /*---------------------------------------------------*/
123
124 /* note that writemode = 2 by default (not 1), so that the returned */
125 /* repeat and incre values will be the actual values for this column. */
126
127 /* If writing nulls to a variable length column then dummy data values */
128 /* must have already been written to the heap. */
129 /* We just have to overwrite the previous values with null values. */
130 /* Set writemode = 0 in this case, to test that values have been written */
131
132 fits_get_coltype(fptr, colnum, &tcode, NULL, NULL, status);
133 if (tcode < 0)
134 writemode = 0; /* this is a variable length column */
135
136 if (abs(tcode) >= TCOMPLEX)
137 { /* treat complex columns as pairs of numbers */
138 largeelem = (largeelem - 1) * 2 + 1;
139 nelem *= 2;
140 }
141
142 if (ffgcprll( fptr, colnum, firstrow, largeelem, nelem, writemode, &scale,
143 &zero, tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre,
144 &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
145 return(*status);
146
147 if (tcode == TSTRING)
148 {
149 if (snull[0] == ASCII_NULL_UNDEFINED)
150 {
151 ffpmsg(
152 "Null value string for ASCII table column is not defined (FTPCLU).");
153 return(*status = NO_NULL);
154 }
155
156 /* allocate buffer to hold the null string. Must write the entire */
157 /* width of the column (twidth bytes) to avoid possible problems */
158 /* with uninitialized FITS blocks, in case the field spans blocks */
159
160 buffsize = maxvalue(20, twidth);
161 cstring = (char *) malloc(buffsize);
162 if (!cstring)
163 return(*status = MEMORY_ALLOCATION);
164
165 memset(cstring, ' ', buffsize); /* initialize with blanks */
166
167 leng = strlen(snull);
168 if (hdutype == BINARY_TBL)
169 leng++; /* copy the terminator too in binary tables */
170
171 strncpy(cstring, snull, leng); /* copy null string to temp buffer */
172 }
173 else if ( tcode == TBYTE ||
174 tcode == TSHORT ||
175 tcode == TLONG ||
176 tcode == TLONGLONG)
177 {
178 if (tnull == NULL_UNDEFINED)
179 {
180 ffpmsg(
181 "Null value for integer table column is not defined (FTPCLU).");
182 return(*status = NO_NULL);
183 }
184
185 if (tcode == TBYTE)
186 i1null = (unsigned char) tnull;
187 else if (tcode == TSHORT)
188 {
189 i2null = (short) tnull;
190 #if BYTESWAPPED
191 ffswap2(&i2null, 1); /* reverse order of bytes */
192 #endif
193 }
194 else if (tcode == TLONG)
195 {
196 i4null = (INT32BIT) tnull;
197 #if BYTESWAPPED
198 ffswap4(&i4null, 1); /* reverse order of bytes */
199 #endif
200 }
201 else
202 {
203 i8null = tnull;
204 #if BYTESWAPPED
205 ffswap8((double *)(&i8null), 1); /* reverse order of bytes */
206 #endif
207 }
208 }
209
210 /*---------------------------------------------------------------------*/
211 /* Now write the pixels to the FITS column. */
212 /*---------------------------------------------------------------------*/
213 remain = nelem; /* remaining number of values to write */
214 next = 0; /* next element in array to be written */
215 rownum = 0; /* row number, relative to firstrow */
216 ntodo = remain; /* number of elements to write at one time */
217
218 while (ntodo)
219 {
220 /* limit the number of pixels to process at one time to the number that
221 will fit in the buffer space or to the number of pixels that remain
222 in the current vector, which ever is smaller.
223 */
224 ntodo = minvalue(ntodo, (repeat - elemnum));
225 wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
226
227 ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
228
229 switch (tcode)
230 {
231 case (TBYTE):
232
233 for (ii = 0; ii < ntodo; ii++)
234 ffpbyt(fptr, 1, &i1null, status);
235 break;
236
237 case (TSHORT):
238
239 for (ii = 0; ii < ntodo; ii++)
240 ffpbyt(fptr, 2, &i2null, status);
241 break;
242
243 case (TLONG):
244
245 for (ii = 0; ii < ntodo; ii++)
246 ffpbyt(fptr, 4, &i4null, status);
247 break;
248
249 case (TLONGLONG):
250
251 for (ii = 0; ii < ntodo; ii++)
252 ffpbyt(fptr, 8, &i8null, status);
253 break;
254
255 case (TFLOAT):
256
257 for (ii = 0; ii < ntodo; ii++)
258 ffpbyt(fptr, 4, jbuff, status);
259 break;
260
261 case (TDOUBLE):
262
263 for (ii = 0; ii < ntodo; ii++)
264 ffpbyt(fptr, 8, jbuff, status);
265 break;
266
267 case (TLOGICAL):
268
269 for (ii = 0; ii < ntodo; ii++)
270 ffpbyt(fptr, 1, &lognul, status);
271 break;
272
273 case (TSTRING): /* an ASCII table column */
274 /* repeat always = 1, so ntodo is also guaranteed to = 1 */
275 ffpbyt(fptr, twidth, cstring, status);
276 break;
277
278 default: /* error trap */
279 snprintf(message,FLEN_ERRMSG,
280 "Cannot write null value to column %d which has format %s",
281 colnum,tform);
282 ffpmsg(message);
283 return(*status);
284
285 } /* End of switch block */
286
287 /*-------------------------*/
288 /* Check for fatal error */
289 /*-------------------------*/
290 if (*status > 0) /* test for error during previous write operation */
291 {
292 snprintf(message,FLEN_ERRMSG,
293 "Error writing %.0f thru %.0f of null values (ffpclu).",
294 (double) (next+1), (double) (next+ntodo));
295 ffpmsg(message);
296
297 if (cstring)
298 free(cstring);
299
300 return(*status);
301 }
302
303 /*--------------------------------------------*/
304 /* increment the counters for the next loop */
305 /*--------------------------------------------*/
306 remain -= ntodo;
307 if (remain)
308 {
309 next += ntodo;
310 elemnum += ntodo;
311 if (elemnum == repeat) /* completed a row; start on next row */
312 {
313 elemnum = 0;
314 rownum++;
315 }
316 }
317 ntodo = remain; /* this is the maximum number to do in next loop */
318
319 } /* End of main while Loop */
320
321 if (cstring)
322 free(cstring);
323
324 return(*status);
325 }
326 /*--------------------------------------------------------------------------*/
ffpcluc(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,int * status)327 int ffpcluc( fitsfile *fptr, /* I - FITS file pointer */
328 int colnum, /* I - number of column to write (1 = 1st col) */
329 LONGLONG firstrow, /* I - first row to write (1 = 1st row) */
330 LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */
331 LONGLONG nelem, /* I - number of values to write */
332 int *status) /* IO - error status */
333 /*
334 Set elements of a table column to the appropriate null value for the column
335 The column number may refer to a real column in an ASCII or binary table,
336 or it may refer to a virtual column in a 1 or more grouped FITS primary
337 array. FITSIO treats a primary array as a binary table
338 with 2 vector columns: the first column contains the group parameters (often
339 with length = 0) and the second column contains the array of image pixels.
340 Each row of the table represents a group in the case of multigroup FITS
341 images.
342
343 This routine does not do anything special in the case of COMPLEX table columns
344 (unlike the similar ffpclu routine). This routine is mainly for use by
345 ffpcne which already compensates for the effective doubling of the number of
346 elements in a complex column.
347 */
348 {
349 int tcode, maxelem, hdutype, writemode = 2, leng;
350 short i2null;
351 INT32BIT i4null;
352 long twidth, incre;
353 LONGLONG ii;
354 LONGLONG tnull, i8null;
355 LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, ntodo;
356 double scale, zero;
357 unsigned char i1null, lognul = 0;
358 char tform[20], *cstring = 0;
359 char message[FLEN_ERRMSG];
360 char snull[20]; /* the FITS null value */
361 long jbuff[2] = { -1, -1}; /* all bits set is equivalent to a NaN */
362 size_t buffsize;
363
364 if (*status > 0) /* inherit input status value if > 0 */
365 return(*status);
366
367 /*---------------------------------------------------*/
368 /* Check input and get parameters about the column: */
369 /*---------------------------------------------------*/
370
371 /* note that writemode = 2 by default (not 1), so that the returned */
372 /* repeat and incre values will be the actual values for this column. */
373
374 /* If writing nulls to a variable length column then dummy data values */
375 /* must have already been written to the heap. */
376 /* We just have to overwrite the previous values with null values. */
377 /* Set writemode = 0 in this case, to test that values have been written */
378
379 fits_get_coltype(fptr, colnum, &tcode, NULL, NULL, status);
380 if (tcode < 0)
381 writemode = 0; /* this is a variable length column */
382
383 if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, writemode, &scale,
384 &zero, tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre,
385 &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
386 return(*status);
387
388 if (tcode == TSTRING)
389 {
390 if (snull[0] == ASCII_NULL_UNDEFINED)
391 {
392 ffpmsg(
393 "Null value string for ASCII table column is not defined (FTPCLU).");
394 return(*status = NO_NULL);
395 }
396
397 /* allocate buffer to hold the null string. Must write the entire */
398 /* width of the column (twidth bytes) to avoid possible problems */
399 /* with uninitialized FITS blocks, in case the field spans blocks */
400
401 buffsize = maxvalue(20, twidth);
402 cstring = (char *) malloc(buffsize);
403 if (!cstring)
404 return(*status = MEMORY_ALLOCATION);
405
406 memset(cstring, ' ', buffsize); /* initialize with blanks */
407
408 leng = strlen(snull);
409 if (hdutype == BINARY_TBL)
410 leng++; /* copy the terminator too in binary tables */
411
412 strncpy(cstring, snull, leng); /* copy null string to temp buffer */
413
414 }
415 else if ( tcode == TBYTE ||
416 tcode == TSHORT ||
417 tcode == TLONG ||
418 tcode == TLONGLONG)
419 {
420 if (tnull == NULL_UNDEFINED)
421 {
422 ffpmsg(
423 "Null value for integer table column is not defined (FTPCLU).");
424 return(*status = NO_NULL);
425 }
426
427 if (tcode == TBYTE)
428 i1null = (unsigned char) tnull;
429 else if (tcode == TSHORT)
430 {
431 i2null = (short) tnull;
432 #if BYTESWAPPED
433 ffswap2(&i2null, 1); /* reverse order of bytes */
434 #endif
435 }
436 else if (tcode == TLONG)
437 {
438 i4null = (INT32BIT) tnull;
439 #if BYTESWAPPED
440 ffswap4(&i4null, 1); /* reverse order of bytes */
441 #endif
442 }
443 else
444 {
445 i8null = tnull;
446 #if BYTESWAPPED
447 ffswap8((double *)(&i8null), 1); /* reverse order of bytes */
448 #endif
449 }
450 }
451
452 /*---------------------------------------------------------------------*/
453 /* Now write the pixels to the FITS column. */
454 /*---------------------------------------------------------------------*/
455 remain = nelem; /* remaining number of values to write */
456 next = 0; /* next element in array to be written */
457 rownum = 0; /* row number, relative to firstrow */
458 ntodo = remain; /* number of elements to write at one time */
459
460 while (ntodo)
461 {
462 /* limit the number of pixels to process at one time to the number that
463 will fit in the buffer space or to the number of pixels that remain
464 in the current vector, which ever is smaller.
465 */
466 ntodo = minvalue(ntodo, (repeat - elemnum));
467 wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
468
469 ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
470
471 switch (tcode)
472 {
473 case (TBYTE):
474
475 for (ii = 0; ii < ntodo; ii++)
476 ffpbyt(fptr, 1, &i1null, status);
477 break;
478
479 case (TSHORT):
480
481 for (ii = 0; ii < ntodo; ii++)
482 ffpbyt(fptr, 2, &i2null, status);
483 break;
484
485 case (TLONG):
486
487 for (ii = 0; ii < ntodo; ii++)
488 ffpbyt(fptr, 4, &i4null, status);
489 break;
490
491 case (TLONGLONG):
492
493 for (ii = 0; ii < ntodo; ii++)
494 ffpbyt(fptr, 8, &i8null, status);
495 break;
496
497 case (TFLOAT):
498
499 for (ii = 0; ii < ntodo; ii++)
500 ffpbyt(fptr, 4, jbuff, status);
501 break;
502
503 case (TDOUBLE):
504
505 for (ii = 0; ii < ntodo; ii++)
506 ffpbyt(fptr, 8, jbuff, status);
507 break;
508
509 case (TLOGICAL):
510
511 for (ii = 0; ii < ntodo; ii++)
512 ffpbyt(fptr, 1, &lognul, status);
513 break;
514
515 case (TSTRING): /* an ASCII table column */
516 /* repeat always = 1, so ntodo is also guaranteed to = 1 */
517 ffpbyt(fptr, twidth, cstring, status);
518 break;
519
520 default: /* error trap */
521 snprintf(message, FLEN_ERRMSG,
522 "Cannot write null value to column %d which has format %s",
523 colnum,tform);
524 ffpmsg(message);
525 return(*status);
526
527 } /* End of switch block */
528
529 /*-------------------------*/
530 /* Check for fatal error */
531 /*-------------------------*/
532 if (*status > 0) /* test for error during previous write operation */
533 {
534 snprintf(message,FLEN_ERRMSG,
535 "Error writing %.0f thru %.0f of null values (ffpclu).",
536 (double) (next+1), (double) (next+ntodo));
537 ffpmsg(message);
538
539 if (cstring)
540 free(cstring);
541
542 return(*status);
543 }
544
545 /*--------------------------------------------*/
546 /* increment the counters for the next loop */
547 /*--------------------------------------------*/
548 remain -= ntodo;
549 if (remain)
550 {
551 next += ntodo;
552 elemnum += ntodo;
553 if (elemnum == repeat) /* completed a row; start on next row */
554 {
555 elemnum = 0;
556 rownum++;
557 }
558 }
559 ntodo = remain; /* this is the maximum number to do in next loop */
560
561 } /* End of main while Loop */
562
563 if (cstring)
564 free(cstring);
565
566 return(*status);
567 }
568 /*--------------------------------------------------------------------------*/
ffprwu(fitsfile * fptr,LONGLONG firstrow,LONGLONG nrows,int * status)569 int ffprwu(fitsfile *fptr,
570 LONGLONG firstrow,
571 LONGLONG nrows,
572 int *status)
573
574 /*
575 * fits_write_nullrows / ffprwu - write TNULLs to all columns in one or more rows
576 *
577 * fitsfile *fptr - pointer to FITS HDU opened for read/write
578 * long int firstrow - first table row to set to null. (firstrow >= 1)
579 * long int nrows - total number or rows to set to null. (nrows >= 1)
580 * int *status - upon return, *status contains CFITSIO status code
581 *
582 * RETURNS: CFITSIO status code
583 *
584 * written by Craig Markwardt, GSFC
585 */
586 {
587 LONGLONG ntotrows;
588 int ncols, i;
589 int typecode = 0;
590 LONGLONG repeat = 0, width = 0;
591 int nullstatus;
592
593 if (*status > 0) return *status;
594
595 if ((firstrow <= 0) || (nrows <= 0)) return (*status = BAD_ROW_NUM);
596
597 fits_get_num_rowsll(fptr, &ntotrows, status);
598
599 if (firstrow + nrows - 1 > ntotrows) return (*status = BAD_ROW_NUM);
600
601 fits_get_num_cols(fptr, &ncols, status);
602 if (*status) return *status;
603
604
605 /* Loop through each column and write nulls */
606 for (i=1; i <= ncols; i++) {
607 repeat = 0; typecode = 0; width = 0;
608 fits_get_coltypell(fptr, i, &typecode, &repeat, &width, status);
609 if (*status) break;
610
611 /* NOTE: data of TSTRING type must not write the total repeat
612 count, since the repeat count is the *character* count, not the
613 nstring count. Divide by string width to get number of
614 strings. */
615
616 if (typecode == TSTRING) repeat /= width;
617
618 /* Write NULLs */
619 nullstatus = 0;
620 fits_write_col_null(fptr, i, firstrow, 1, repeat*nrows, &nullstatus);
621
622 /* ignore error if no null value is defined for the column */
623 if (nullstatus && nullstatus != NO_NULL) return (*status = nullstatus);
624
625 }
626
627 return *status;
628 }
629
630