Instrument Neutral Distributed Interface INDI 2.2.5
fits.c
Go to the documentation of this file.
1/*
2* DSP API - a digital signal processing library for astronomy usage
3* Copyright © 2017-2022 Ilia Platone
4*
5* This program is free software; you can redistribute it and/or
6* modify it under the terms of the GNU Lesser General Public
7* License as published by the Free Software Foundation; either
8* version 3 of the License, or (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13* Lesser General Public License for more details.
14*
15* You should have received a copy of the GNU Lesser General Public License
16* along with this program; if not, write to the Free Software Foundation,
17* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18*/
19
20#include "dsp.h"
21
22void dsp_fits_update_fits_key(fitsfile *fptr, int type, char* name, void *p, char* explanation, int *status)
23{
24 fits_update_key(fptr, type, name, p, explanation, status);
25}
26
27long dsp_fits_alloc_fits_rows(fitsfile *fptr, unsigned long num_rows)
28{
29 int status = 0;
30 long nrows = 0;
31 fits_get_num_rows(fptr, &nrows, &status);
32 fits_insert_rows(fptr, nrows, num_rows, &status);
33 return nrows;
34}
35
36
37int dsp_fits_fill_fits_col(fitsfile *fptr, char* name, unsigned char *buf, int typecode, long num_elements, unsigned long rown)
38{
39 int status = 0;
40 int ncol = 0;
41 fits_get_colnum(fptr, CASESEN, (char*)(name), &ncol, &status);
42 if(status != COL_NOT_FOUND)
43 {
44 fits_write_col(fptr, typecode, ncol, rown, 1, num_elements, buf, &status);
45 }
46 return status;
47}
48
49int dsp_fits_append_fits_col(fitsfile *fptr, char* name, char* format)
50{
51 int status = 0;
52 int ncols = 0;
53 fits_get_colnum(fptr, CASESEN, (char*)(name), &ncols, &status);
54 if(status == COL_NOT_FOUND)
55 {
56 fits_get_num_cols(fptr, &ncols, &status);
57 fits_insert_col(fptr, ncols++, name, format, &status);
58 }
59 return ncols;
60}
61
62void dsp_fits_delete_fits_col(fitsfile *fptr, char* name)
63{
64 int status = 0;
65 int ncol = 0;
66 fits_get_colnum(fptr, CASESEN, (char*)(name), &ncol, &status);
67 while(status != COL_NOT_FOUND)
68 fits_delete_col(fptr, ncol, &status);
69}
70
71fitsfile* dsp_fits_create_fits(size_t *size, void **buf)
72{
73 fitsfile *fptr = NULL;
74
75 size_t memsize;
76 int status = 0;
77 char error_status[64];
78
79 // Now we have to send fits format data to the client
80 memsize = 5760;
81 void* memptr = malloc(memsize);
82 if (!memptr)
83 {
84 perr("Error: failed to allocate memory: %lu", (unsigned long)(memsize));
85 }
86
87 fits_create_memfile(&fptr, &memptr, &memsize, 2880, realloc, &status);
88
89 if (status)
90 {
91 fits_get_errstatus(status, error_status);
92 perr("FITS Error: %s", error_status);
93 if(memptr != NULL)
94 free(memptr);
95 return NULL;
96 }
97 if (status)
98 {
99 fits_get_errstatus(status, error_status);
100 perr("FITS Error: %s", error_status);
101 if(memptr != NULL)
102 free(memptr);
103 return NULL;
104 }
105
106 if (status)
107 {
108 fits_get_errstatus(status, error_status);
109 perr("FITS Error: %s", error_status);
110 if(memptr != NULL)
111 free(memptr);
112 return NULL;
113 }
114
115 *size = memsize;
116 *buf = memptr;
117
118 return fptr;
119}
120
121int dsp_fits_close_fits(fitsfile *fptr)
122{
123 int status = 0;
124 fits_close_file(fptr, &status);
125
126 return status;
127}
128
129int dsp_fits_get_value(fitsfile *fptr, char* column, long rown, void **retval)
130{
131 int err = 1, n = 0, anynul = 0, status = 0, typecode;
132 long repeat = 1;
133 long width;
134 char name[64];
135 if(column == NULL)
136 goto err_return;
137 fits_get_colname(fptr, 0, column, name, &n, &status);
138 if(status)
139 goto err_return;
140 fits_get_coltype(fptr, n, &typecode, &repeat, &width, &status);
141 void *value = malloc(dsp_fits_get_element_size(typecode)*(size_t)(repeat*width));
142 fits_read_col(fptr, typecode, n, rown, 1, repeat, NULL, value, &anynul, &status);
143 *retval = value;
144err_return:
145 return err;
146}
147
148int dsp_fits_check_column(fitsfile *fptr, char* column, char **expected, long rown)
149{
150 int err = 1, n = 0, anynul = 0, status = 0, x, y, typecode;
151 long repeat = 1;
152 long width;
153 char name[64];
154 if(column == NULL || expected == NULL)
155 goto err_return;
156 fits_get_colname(fptr, 0, column, name, &n, &status);
157 if(status)
158 goto err_return;
159 fits_get_coltype(fptr, n, &typecode, &repeat, &width, &status);
160 if(typecode != TSTRING)
161 goto err_return;
162 char **value = (char **)malloc(sizeof(char*)*(size_t)repeat);
163 for(x = 0; x < repeat; x++) {
164 value[x] = (char*) malloc((size_t)width);
165 fits_read_col_str(fptr, n, rown, 1, 1, NULL, value, &anynul, &status);
166 for(y = 0; strcmp(expected[y], ""); y++) {
167 if(!strcmp(value[x], expected[y])) {
168 err &= 1;
169 break;
170 }
171 }
172 if(y == 0)
173 err = 0;
174 }
175 for(x = 0; x < repeat; x++)
176 free(value[x]);
177 free(value);
178err_return:
179 return err;
180}
181
182int dsp_fits_check_key(fitsfile *fptr, char* keyname, char **expected)
183{
184 int err = 1, status = 0, y;
185 char value[64];
186 if(keyname == NULL || expected == NULL)
187 goto err_return;
188 fits_read_key_str(fptr, keyname, value, NULL, &status);
189 if(status)
190 goto err_return;
191 for(y = 0; strcmp(expected[y], ""); y++) {
192 if(!strcmp(value, expected[y])) {
193 err &= 1;
194 break;
195 }
196 }
197 if(y == 0)
198 err = 0;
199err_return:
200 return err;
201}
202
203int dsp_fits_read_typecode(char* typestr, int *typecode, long *width, long *repeat)
204{
205 int w, r, t;
206 char c;
207 sscanf(typestr, "%d%c%d", &w, &c, &r);
208 t = (int)c;
209 if (t == EXTFITS_ELEMENT_BIT.typestr[0])
210 t = EXTFITS_ELEMENT_BIT.typecode;
211 if (t == EXTFITS_ELEMENT_STRING.typestr[0])
212 t = EXTFITS_ELEMENT_STRING.typecode;
213 if (t == EXTFITS_ELEMENT_LOGICAL.typestr[0])
214 t = EXTFITS_ELEMENT_LOGICAL.typecode;
215 if (t == EXTFITS_ELEMENT_BYTE.typestr[0])
216 t = EXTFITS_ELEMENT_BYTE.typecode;
217 if (t == EXTFITS_ELEMENT_SBYTE.typestr[0])
218 t = EXTFITS_ELEMENT_SBYTE.typecode;
219 if (t == EXTFITS_ELEMENT_SHORT.typestr[0])
220 t = EXTFITS_ELEMENT_SHORT.typecode;
221 if (t == EXTFITS_ELEMENT_USHORT.typestr[0])
222 t = EXTFITS_ELEMENT_USHORT.typecode;
223 if (t == EXTFITS_ELEMENT_INT.typestr[0])
224 t = EXTFITS_ELEMENT_INT.typecode;
225 if (t == EXTFITS_ELEMENT_UINT.typestr[0])
226 t = EXTFITS_ELEMENT_UINT.typecode;
227 if (t == EXTFITS_ELEMENT_LONG.typestr[0])
228 t = EXTFITS_ELEMENT_LONG.typecode;
229 if (t == EXTFITS_ELEMENT_FLOAT.typestr[0])
230 t = EXTFITS_ELEMENT_FLOAT.typecode;
231 if (t == EXTFITS_ELEMENT_DOUBLE.typestr[0])
232 t = EXTFITS_ELEMENT_DOUBLE.typecode;
233 if (t == EXTFITS_ELEMENT_COMPLEX.typestr[0])
234 t = EXTFITS_ELEMENT_COMPLEX.typecode;
235 if (t == EXTFITS_ELEMENT_DBLCOMPLEX.typestr[0])
236 t = EXTFITS_ELEMENT_DBLCOMPLEX.typecode;
237 else return -1;
238 *typecode = t;
239 *width = w;
240 *repeat = r;
241 return 0;
242}
243
244size_t dsp_fits_get_element_size(int typecode)
245{
246 size_t typesize = 1;
247
248 switch(typecode)
249 {
250 case TSHORT:
251 case TUSHORT:
252 typesize *= 2;
253 break;
254 case TINT:
255 case TUINT:
256 case TFLOAT:
257 typesize *= 4;
258 break;
259 case TLONG:
260 case TULONG:
261 case TDOUBLE:
262 case TCOMPLEX:
263 typesize *= 8;
264 break;
265 case TDBLCOMPLEX:
266 typesize *= 16;
267 break;
268 default:
269 break;
270 }
271
272 return typesize;
273}
274
275int dsp_fits_append_table(fitsfile* fptr, dsp_fits_column *columns, int ncols, char* tablename)
276{
277 int status = 0;
278 int x = 0;
279 fits_update_key(fptr, TSTRING, "EXTNAME", tablename, "", &status);
280 for(x = 0; x < ncols; x++) {
281 dsp_fits_append_fits_col(fptr, columns[x].name, columns[x].format);
282 }
283 return status;
284}
285
286dsp_fits_row* dsp_fits_read_sdfits(char *filename, long *num_rows, long *maxes, long **maxis)
287{
288 fitsfile *fptr = (fitsfile*)malloc(sizeof(fitsfile));
289 memset(fptr, 0, sizeof(fitsfile));
290 int status = 0;
291 int sdfits_hdu = 0;
292 long nrows = 0;
293 long r = 0;
294 long nmatrix = 0;
295 int ncols = 0;
296 int typecode = 0;
297 long width = 0;
298 long repeat = 0;
299 int k = 0;
300 int i = 0;
301 int n = 0;
302 int dim;
303 int anynul = 0;
304 long naxes[3] = { 1, 1, 1 };
305 dsp_fits_column* columns = (dsp_fits_column*)malloc(sizeof(dsp_fits_column));
306 dsp_fits_row* rows = (dsp_fits_row*)malloc(sizeof(dsp_fits_row));
307 char value[150];
308 char comment[150];
309 char error_status[64];
310
311 fits_open_file(&fptr, filename, READONLY, &status);
312 if (status)
313 {
314 goto fail;
315 }
316
317 ffgkey(fptr, FITS_KEYWORD_EXTEND.name, value, comment, &status);
318 if(status || strcmp(value, FITS_KEYWORD_EXTEND.value))
319 {
320 goto fail;
321 }
322
323 ffgkey(fptr, SDFITS_KEYWORD_TELESCOP.name, value, comment, &status);
324 if (!status)
325 {
326 }
327 status = 0;
328
329 ffgkey(fptr, SDFITS_KEYWORD_OBSERVER.name, value, comment, &status);
330 if (!status)
331 {
332 }
333 status = 0;
334
335 ffgkey(fptr, SDFITS_KEYWORD_DATE_OBS.name, value, comment, &status);
336 if (!status)
337 {
338 }
339 status = 0;
340
341 ffgkey(fptr, SDFITS_KEYWORD_DATAMAX.name, value, comment, &status);
342 if (!status)
343 {
344 }
345 status = 0;
346
347 ffgkey(fptr, SDFITS_KEYWORD_DATAMIN.name, value, comment, &status);
348 if (!status)
349 {
350 }
351 status = 0;
352
353 fits_movabs_hdu(fptr, 1, &sdfits_hdu, &status);
354 if(status || sdfits_hdu != BINARY_TBL)
355 {
356 goto fail;
357 }
358
359 fits_read_key_str(fptr, "EXTNAME", value, comment, &status);
360 if(status || strcmp(value, FITS_TABLE_SDFITS))
361 {
362 goto fail;
363 }
364
365 fits_read_key_str(fptr, EXTFITS_KEYWORD_NMATRIX.name, value, NULL, &status);
366 if(status || strcmp(value, EXTFITS_KEYWORD_NMATRIX.value)) {
367 goto fail;
368 }
369
370 fits_get_num_rows(fptr, &nrows, &status);
371 if(status)
372 {
373 goto fail;
374 }
375
376 fits_get_num_cols(fptr, &ncols, &status);
377 if(status)
378 {
379 goto fail;
380 }
381
382 fits_read_key_lng(fptr, EXTFITS_KEYWORD_NMATRIX.name, &nmatrix, NULL, &status);
383 if(status || nmatrix < 1)
384 {
385 goto fail;
386 }
387
388 columns = (dsp_fits_column*)realloc(columns, sizeof(dsp_fits_column)*((size_t)ncols+1));
389 rows = (dsp_fits_row*)realloc(rows, sizeof(dsp_fits_row)*((size_t)nrows+1));
390
391 for(r = 0; r < nrows; r++) {
392 for(k = 0; k < ncols; k++) {
393 columns[k].name = (char*)malloc(150);
394 columns[k].format = (char*)malloc(150);
395 columns[k].unit = (char*)malloc(150);
396 columns[k].value = (char*)malloc(150);
397 columns[k].comment = (char*)malloc(150);
398
399 status = 0;
400 fits_get_colname(fptr, 0, SDFITS_TABLE_MAIN[i].name, value, &n, &status);
401 strcpy(columns[k].name, value);
402 if(!dsp_fits_check_key(fptr, EXTFITS_KEYWORD_TMATX(k).name, &EXTFITS_KEYWORD_TMATX(k).value)) {
403 int max_dims = 5;
404 int dims;
405 long *sizes =(long*)malloc(sizeof(long)*(size_t)max_dims);
406 fits_read_tdim(fptr, k, max_dims, &dims, sizes, &status);
407 if(dims < 2) {
408 long d = 0;
409 fits_read_key_lng(fptr, EXTFITS_KEYWORD_MAXIS().name, &d, NULL, &status);
410 sizes = (long*)malloc(sizeof(long)*(size_t)dims);
411 for(dim = 0; dim < d; dim++)
412 fits_read_key_lng(fptr, EXTFITS_KEYWORD_MAXIS(dim).name, &sizes[dim], NULL, &status);
413 dims = (int)d;
414 }
415 if(dims > 0) {
416 void *tcs = NULL;
417 dsp_fits_get_value(fptr, EXTFITS_KEYWORD_TMATX(k).axes_definition.format.name, r, &tcs);
418 strcpy(columns[k].format, tcs);
419 dsp_fits_get_value(fptr, EXTFITS_KEYWORD_TMATX(k).axes_definition.unit.name, r, &tcs);
420 strcpy(columns[k].unit, tcs);
421 if (!dsp_fits_read_typecode((char*)tcs, &typecode, &width, &repeat)) {
422 size_t element_size = dsp_fits_get_element_size(typecode);
423 long nelements = 1;
424 for(dim = 0; dim < dims; dim++) {
425 nelements *= naxes[dim];
426 }
427 columns[k].value = (char*)malloc(element_size*(size_t)nelements);
428 fits_read_col(fptr, typecode, k, r, 1, nelements, NULL, columns->value, &anynul, &status);
429 if(!anynul && !status) {
430 *maxis = (long*)malloc(sizeof(long)*(size_t)dims);
431 for(dim = 0; dim < dims; dim++)
432 *maxis[dim] = naxes[dim];
433 *maxes = dims;
434 }
435 }
436 }
437 } else {
438 int typecode;
439 long repeat, width;
440 fits_get_eqcoltype(fptr, n, &typecode, &repeat, &width, &status);
441 if(status) continue;
442 if(dsp_fits_check_column(fptr, columns[k].name, columns[k].expected, r))
443 continue;
444 void *val = &columns[k].value;
445 dsp_fits_get_value(fptr, columns[k].name, r, &val);
446 }
447 }
448 rows[r].columns = (dsp_fits_column*)malloc(sizeof(dsp_fits_column)*rows[r].num_columns);
449 rows[r].num_columns = (size_t)ncols;
450 }
451 *num_rows = nrows;
452 status = 0;
453 fits_close_file(fptr, &status);
454 if(status)
455 goto fail;
456 return rows;
457fail:
458 free(rows);
459 free(columns);
460 if(status)
461 {
462 fits_get_errstatus(status, error_status);
463 perr("FITS Error: %s\n", error_status);
464 }
465 return NULL;
466}
int dsp_fits_append_table(fitsfile *fptr, dsp_fits_column *columns, int ncols, char *tablename)
Definition fits.c:275
int dsp_fits_check_key(fitsfile *fptr, char *keyname, char **expected)
Definition fits.c:182
#define perr(...)
Definition dsp.h:161
dsp_fits_row * dsp_fits_read_sdfits(char *filename, long *num_rows, long *maxes, long **maxis)
read a fits file containing a SDFITS Extension
Definition fits.c:286
#define SDFITS_KEYWORD_DATE_OBS
UT date of observation (dd/mm/yy) .
Definition sdfits.h:283
#define SDFITS_TABLE_MAIN
Definition sdfits.h:222
#define SDFITS_KEYWORD_DATAMAX
Max spectral value (K) - for whole file.
Definition sdfits.h:285
#define FITS_TABLE_SDFITS
SDFITS Convention Table.
Definition sdfits.h:31
#define SDFITS_KEYWORD_OBSERVER
Name of observer.
Definition sdfits.h:281
#define SDFITS_KEYWORD_DATAMIN
Min spectral value (K) - for whole file.
Definition sdfits.h:287
#define SDFITS_KEYWORD_TELESCOP
Definition sdfits.h:279
int dsp_fits_fill_fits_col(fitsfile *fptr, char *name, unsigned char *buf, int typecode, long num_elements, unsigned long rown)
Fill a column at the given row position with the valued buffer.
Definition fits.c:37
#define EXTFITS_ELEMENT_LOGICAL
Definition fits.h:153
#define EXTFITS_KEYWORD_MAXIS(m)
M = number axes in regular matrix, Number pixels on axis m = 1 to M.
Definition fits.h:208
int dsp_fits_close_fits(fitsfile *fptr)
Close a fits file pointer.
Definition fits.c:121
#define EXTFITS_ELEMENT_FLOAT
Definition fits.h:162
#define EXTFITS_ELEMENT_INT
Definition fits.h:159
#define EXTFITS_ELEMENT_COMPLEX
Definition fits.h:164
#define EXTFITS_KEYWORD_TMATX(n)
Set to 'T' — column n contains the visibility matrix.
Definition fits.h:206
int dsp_fits_append_fits_col(fitsfile *fptr, char *name, char *format)
Add a column to the binary table.
Definition fits.c:49
#define EXTFITS_ELEMENT_LONG
Definition fits.h:161
#define FITS_KEYWORD_EXTEND
Definition fits.h:215
int dsp_fits_get_value(fitsfile *fptr, char *column, long rown, void **retval)
Obtain the value of the specified field.
Definition fits.c:129
long dsp_fits_alloc_fits_rows(fitsfile *fptr, unsigned long num_rows)
Convert an RGB color dsp_t array into a dsp_stream_p array each element containing the single compone...
Definition fits.c:27
int dsp_fits_read_typecode(char *typestr, int *typecode, long *width, long *repeat)
Decode a typecode format string.
Definition fits.c:203
#define EXTFITS_KEYWORD_NMATRIX
NMATRIX shall be present with the value 1.
Definition fits.h:204
#define EXTFITS_ELEMENT_DBLCOMPLEX
Definition fits.h:165
#define EXTFITS_ELEMENT_UINT
Definition fits.h:160
#define EXTFITS_ELEMENT_USHORT
Definition fits.h:158
#define EXTFITS_ELEMENT_SHORT
Definition fits.h:157
#define EXTFITS_ELEMENT_BIT
Definition fits.h:154
#define EXTFITS_ELEMENT_STRING
FITS element types.
Definition fits.h:152
int dsp_fits_check_column(fitsfile *fptr, char *column, char **expected, long rown)
Check if the value of the specified field corresponds to a subset of values.
Definition fits.c:148
fitsfile * dsp_fits_create_fits(size_t *size, void **buf)
Create an open fits file pointer to be updated later.
Definition fits.c:71
void dsp_fits_update_fits_key(fitsfile *fptr, int type, char *name, void *p, char *explanation, int *status)
Create or update a new fits header key.
Definition fits.c:22
size_t dsp_fits_get_element_size(int typecode)
Obtain the single element size in bytes.
Definition fits.c:244
#define EXTFITS_ELEMENT_SBYTE
Definition fits.h:156
void dsp_fits_delete_fits_col(fitsfile *fptr, char *name)
Delete a column from the binary table.
Definition fits.c:62
#define EXTFITS_ELEMENT_BYTE
Definition fits.h:155
#define EXTFITS_ELEMENT_DOUBLE
Definition fits.h:163
uint16_t type
Definition pwc-ioctl.h:0
Binary table FITS extension column.
Definition fits.h:69
char * format
Format string of the content of the column (TFORM)
Definition fits.h:73
char * comment
Description of the column or data.
Definition fits.h:79
char * name
Name of the column (title, TTYPE)
Definition fits.h:71
char * unit
Measure unit of the column elements (TUNIT)
Definition fits.h:75
char * value
Default initial value.
Definition fits.h:77
Binary table FITS extension row.
Definition fits.h:86
size_t num_columns
Columns data.
Definition fits.h:90
dsp_fits_column * columns
Columns array.
Definition fits.h:88