Instrument Neutral Distributed Interface INDI  2.0.2
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 
22 void 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 
27 long 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 
37 int 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 
49 int 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 
62 void 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 
71 fitsfile* 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 
121 int dsp_fits_close_fits(fitsfile *fptr)
122 {
123  int status = 0;
124  fits_close_file(fptr, &status);
125 
126  return status;
127 }
128 
129 int 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;
144 err_return:
145  return err;
146 }
147 
148 int 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);
178 err_return:
179  return err;
180 }
181 
182 int 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;
199 err_return:
200  return err;
201 }
202 
203 int 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 
244 size_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 
275 int 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 
286 dsp_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;
457 fail:
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:153
#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
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_TELESCOP
Definition: sdfits.h:279
int dsp_fits_close_fits(fitsfile *fptr)
Close a fits file pointer.
Definition: fits.c:121
#define EXTFITS_ELEMENT_LOGICAL
Definition: fits.h:153
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
#define EXTFITS_KEYWORD_MAXIS(m)
M = number axes in regular matrix, Number pixels on axis m = 1 to M.
Definition: fits.h:208
#define EXTFITS_ELEMENT_FLOAT
Definition: fits.h:162
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
#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
#define EXTFITS_ELEMENT_LONG
Definition: fits.h:161
#define FITS_KEYWORD_EXTEND
Definition: fits.h:215
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
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
fitsfile * dsp_fits_create_fits(size_t *size, void **buf)
Create an open fits file pointer to be updated later.
Definition: fits.c:71
#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
int dsp_fits_read_typecode(char *typestr, int *typecode, long *width, long *repeat)
Decode a typecode format string.
Definition: fits.c:203
#define EXTFITS_ELEMENT_STRING
FITS element types.
Definition: fits.h:152
void dsp_fits_delete_fits_col(fitsfile *fptr, char *name)
Delete a column from the binary table.
Definition: fits.c:62
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_SBYTE
Definition: fits.h:156
size_t dsp_fits_get_element_size(int typecode)
Obtain the single element size in bytes.
Definition: fits.c:244
#define EXTFITS_ELEMENT_BYTE
Definition: fits.h:155
#define EXTFITS_ELEMENT_DOUBLE
Definition: fits.h:163
int dsp_fits_get_value(fitsfile *fptr, char *column, long rown, void **retval)
Obtain the value of the specified field.
Definition: fits.c:129
__le16 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