1 /* This file, putcols.c, contains routines that write data elements to */
2 /* a FITS image or table, of type character string. */
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 /*--------------------------------------------------------------------------*/
ffpcls(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,char ** array,int * status)12 int ffpcls( fitsfile *fptr, /* I - FITS file pointer */
13 int colnum, /* I - number of column to write (1 = 1st col) */
14 LONGLONG firstrow, /* I - first row to write (1 = 1st row) */
15 LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */
16 LONGLONG nelem, /* I - number of strings to write */
17 char **array, /* I - array of pointers to strings */
18 int *status) /* IO - error status */
19 /*
20 Write an array of string values to a column in the current FITS HDU.
21 */
22 {
23 int tcode, maxelem, hdutype, nchar;
24 long twidth, incre;
25 long ii, jj, ntodo;
26 LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
27 double scale, zero;
28 char tform[20], *blanks;
29 char message[FLEN_ERRMSG];
30 char snull[20]; /* the FITS null value */
31 tcolumn *colptr;
32
33 double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
34 char *buffer, *arrayptr;
35
36 if (*status > 0) /* inherit input status value if > 0 */
37 return(*status);
38
39 /* reset position to the correct HDU if necessary */
40 if (fptr->HDUposition != (fptr->Fptr)->curhdu)
41 {
42 ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
43 }
44 else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
45 {
46 if ( ffrdef(fptr, status) > 0) /* rescan header */
47 return(*status);
48 }
49
50 /*---------------------------------------------------*/
51 /* Check input and get parameters about the column: */
52 /*---------------------------------------------------*/
53 if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
54 {
55 snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d",
56 colnum);
57 ffpmsg(message);
58 return(*status = BAD_COL_NUM);
59 }
60
61 colptr = (fptr->Fptr)->tableptr; /* point to first column */
62 colptr += (colnum - 1); /* offset to correct column structure */
63 tcode = colptr->tdatatype;
64
65 if (tcode == -TSTRING) /* variable length column in a binary table? */
66 {
67 /* only write a single string; ignore value of firstelem */
68 nchar = maxvalue(1,strlen(array[0])); /* will write at least 1 char */
69 /* even if input string is null */
70
71 if (ffgcprll( fptr, colnum, firstrow, 1, nchar, 1, &scale, &zero,
72 tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre,
73 &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
74 return(*status);
75
76 /* simply move to write position, then write the string */
77 ffmbyt(fptr, startpos, IGNORE_EOF, status);
78 ffpbyt(fptr, nchar, array[0], status);
79
80 if (*status > 0) /* test for error during previous write operation */
81 {
82 snprintf(message,FLEN_ERRMSG,
83 "Error writing to variable length string column (ffpcls).");
84 ffpmsg(message);
85 }
86
87 return(*status);
88 }
89 else if (tcode == TSTRING)
90 {
91 if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
92 tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre,
93 &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
94 return(*status);
95
96 /* if string length is greater than a FITS block (2880 char) then must */
97 /* only write 1 string at a time, to force writein by ffpbyt instead of */
98 /* ffpbytoff (ffpbytoff can't handle this case) */
99 if (twidth > IOBUFLEN) {
100 maxelem = 1;
101 incre = twidth;
102 repeat = 1;
103 }
104
105 blanks = (char *) malloc(twidth); /* string for blank fill values */
106 if (!blanks)
107 {
108 ffpmsg("Could not allocate memory for string (ffpcls)");
109 return(*status = ARRAY_TOO_BIG);
110 }
111
112 for (ii = 0; ii < twidth; ii++)
113 blanks[ii] = ' '; /* fill string with blanks */
114
115 remain = nelem; /* remaining number of values to write */
116 }
117 else
118 return(*status = NOT_ASCII_COL);
119
120 /*-------------------------------------------------------*/
121 /* Now write the strings to the FITS column. */
122 /*-------------------------------------------------------*/
123
124 next = 0; /* next element in array to be written */
125 rownum = 0; /* row number, relative to firstrow */
126
127 while (remain)
128 {
129 /* limit the number of pixels to process at one time to the number that
130 will fit in the buffer space or to the number of pixels that remain
131 in the current vector, which ever is smaller.
132 */
133 ntodo = (long) minvalue(remain, maxelem);
134 ntodo = (long) minvalue(ntodo, (repeat - elemnum));
135
136 wrtptr = startpos + (rownum * rowlen) + (elemnum * incre);
137 ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
138
139 buffer = (char *) cbuff;
140
141 /* copy the user's strings into the buffer */
142 for (ii = 0; ii < ntodo; ii++)
143 {
144 arrayptr = array[next];
145
146 for (jj = 0; jj < twidth; jj++) /* copy the string, char by char */
147 {
148 if (*arrayptr)
149 {
150 *buffer = *arrayptr;
151 buffer++;
152 arrayptr++;
153 }
154 else
155 break;
156 }
157
158 for (;jj < twidth; jj++) /* fill field with blanks, if needed */
159 {
160 *buffer = ' ';
161 buffer++;
162 }
163
164 next++;
165 }
166
167 /* write the buffer full of strings to the FITS file */
168 if (incre == twidth)
169 ffpbyt(fptr, ntodo * twidth, cbuff, status);
170 else
171 ffpbytoff(fptr, twidth, ntodo, incre - twidth, cbuff, status);
172
173 if (*status > 0) /* test for error during previous write operation */
174 {
175 snprintf(message,FLEN_ERRMSG,
176 "Error writing elements %.0f thru %.0f of input data array (ffpcls).",
177 (double) (next+1), (double) (next+ntodo));
178 ffpmsg(message);
179
180 if (blanks)
181 free(blanks);
182
183 return(*status);
184 }
185
186 /*--------------------------------------------*/
187 /* increment the counters for the next loop */
188 /*--------------------------------------------*/
189 remain -= ntodo;
190 if (remain)
191 {
192 elemnum += ntodo;
193 if (elemnum == repeat) /* completed a row; start on next row */
194 {
195 elemnum = 0;
196 rownum++;
197 }
198 }
199 } /* End of main while Loop */
200
201 if (blanks)
202 free(blanks);
203
204 return(*status);
205 }
206 /*--------------------------------------------------------------------------*/
ffpcns(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,char ** array,char * nulvalue,int * status)207 int ffpcns( fitsfile *fptr, /* I - FITS file pointer */
208 int colnum, /* I - number of column to write (1 = 1st col) */
209 LONGLONG firstrow, /* I - first row to write (1 = 1st row) */
210 LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */
211 LONGLONG nelem, /* I - number of values to write */
212 char **array, /* I - array of values to write */
213 char *nulvalue, /* I - string representing a null value */
214 int *status) /* IO - error status */
215 /*
216 Write an array of elements to the specified column of a table. Any input
217 pixels flagged as null will be replaced by the appropriate
218 null value in the output FITS file.
219 */
220 {
221 long repeat, width;
222 LONGLONG ngood = 0, nbad = 0, ii;
223 LONGLONG first, fstelm, fstrow;
224
225 if (*status > 0)
226 return(*status);
227
228 /* reset position to the correct HDU if necessary */
229 if (fptr->HDUposition != (fptr->Fptr)->curhdu)
230 {
231 ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
232 }
233 else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
234 {
235 if ( ffrdef(fptr, status) > 0) /* rescan header */
236 return(*status);
237 }
238
239 /* get the vector repeat length of the column */
240 ffgtcl(fptr, colnum, NULL, &repeat, &width, status);
241
242 if ((fptr->Fptr)->hdutype == BINARY_TBL)
243 repeat = repeat / width; /* convert from chars to unit strings */
244
245 /* absolute element number in the column */
246 first = (firstrow - 1) * repeat + firstelem;
247
248 for (ii = 0; ii < nelem; ii++)
249 {
250 if (strcmp(nulvalue, array[ii])) /* is this a good pixel? */
251 {
252 if (nbad) /* write previous string of bad pixels */
253 {
254 fstelm = ii - nbad + first; /* absolute element number */
255 fstrow = (fstelm - 1) / repeat + 1; /* starting row number */
256 fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */
257
258 if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
259 return(*status);
260 nbad=0;
261 }
262
263 ngood = ngood +1; /* the consecutive number of good pixels */
264 }
265 else
266 {
267 if (ngood) /* write previous string of good pixels */
268 {
269 fstelm = ii - ngood + first; /* absolute element number */
270 fstrow = (fstelm - 1) / repeat + 1; /* starting row number */
271 fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */
272
273 if (ffpcls(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
274 status) > 0)
275 return(*status);
276
277 ngood=0;
278 }
279
280 nbad = nbad +1; /* the consecutive number of bad pixels */
281 }
282 }
283
284 /* finished loop; now just write the last set of pixels */
285
286 if (ngood) /* write last string of good pixels */
287 {
288 fstelm = ii - ngood + first; /* absolute element number */
289 fstrow = (fstelm - 1) / repeat + 1; /* starting row number */
290 fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */
291
292 ffpcls(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
293 }
294 else if (nbad) /* write last string of bad pixels */
295 {
296 fstelm = ii - nbad + first; /* absolute element number */
297 fstrow = (fstelm - 1) / repeat + 1; /* starting row number */
298 fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */
299
300 ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
301 }
302
303 return(*status);
304 }
305