public software.sextractor

[/] [trunk/] [src/] [fits/] [fitshead.c] - Blame information for rev 233

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 bertin
/*
2 233 bertin
*                               fitshead.c
3 2 bertin
*
4 233 bertin
* General functions for handling FITS file headers
5 2 bertin
*
6 233 bertin
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7 2 bertin
*
8 233 bertin
*       This file part of:      AstrOmatic FITS/LDAC library
9 2 bertin
*
10 233 bertin
*       Copyright:              (C) 1998-2010 IAP/CNRS/UPMC
11
*                               (C) 1997 European Southern Observatory
12
*                               (C) 1995,1996 Sterrewacht Leiden
13 2 bertin
*
14 233 bertin
*       Author:                 Emmanuel Bertin (IAP)
15
*
16
*       License:                GNU General Public License
17
*
18
*       AstrOmatic software is free software: you can redistribute it and/or
19
*       modify it under the terms of the GNU General Public License as
20
*       published by the Free Software Foundation, either version 3 of the
21
*       License, or (at your option) any later version.
22
*       AstrOmatic software is distributed in the hope that it will be useful,
23
*       but WITHOUT ANY WARRANTY; without even the implied warranty of
24
*       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
*       GNU General Public License for more details.
26
*       You should have received a copy of the GNU General Public License
27
*       along with AstrOmatic software.
28
*       If not, see <http://www.gnu.org/licenses/>.
29
*
30
*       Last modified:          09/10/2010
31
*
32
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
33 2 bertin
 
34
#ifdef  HAVE_CONFIG_H
35
#include "config.h"
36
#endif
37
 
38
#include        <stdio.h>
39
#include        <stdlib.h>
40
#include        <string.h>
41
 
42
#include        "fitscat_defs.h"
43
#include        "fitscat.h"
44
 
45
extern  char    histokeys[][12];
46 215 bertin
const int       t_size[] = {1, 2, 4, 8, 4, 8, 1};/* size in bytes per t_type */
47 2 bertin
 
48
/******* get_head *************************************************************
49
PROTO   int get_head(tabstruct *tab)
50
PURPOSE Read a FITS header.
51
INPUT   Table structure.
52
OUTPUT  RETURN_OK if a FITS header has been found and loaded, or RETURN_ERROR
53
        otherwise.
54
NOTES   The file must be opened, and the file pointer must be located at
55
        the beginning of a header.
56
        The headbuf pointer in the catstruct is reallocated.
57
AUTHOR  E. Bertin (IAP & Leiden observatory)
58
VERSION 08/02/96
59
 ***/
60
int     get_head(tabstruct *tab)
61
 
62
  {
63
   catstruct    *cat;
64
   int          i;
65
   char         *buf;
66
 
67
  buf = tab->headbuf;
68
  if (!(cat = tab->cat))
69
    error(EXIT_FAILURE, "*Internal Error*: Table has no parent catalog","!");
70
 
71
  QFREE(buf);
72
  QMALLOC(buf, char, FBSIZE);
73
 
74
/*Read the first block and check that it is FITS */
75
  if (!fread(buf, FBSIZE, 1, cat->file))
76
    {
77
    QFREE(buf);
78
    return RETURN_ERROR;
79
    }
80
 
81
  if (strncmp(buf, "SIMPLE  ", 8) && strncmp(buf, "XTENSION", 8))
82
    {
83
    QFREE(buf);
84
    return RETURN_ERROR;
85
    }
86
 
87
/*Find the number of FITS blocks of the header while reading it */
88
  for (i=1; !fitsnfind(buf,"END     ", i); i++)
89
    {
90
    QREALLOC(buf, char, FBSIZE*(i+1));
91
    QFREAD(&buf[FBSIZE*i], FBSIZE, cat->file, cat->filename);
92
    }
93
 
94
  tab->headnblock = i;
95
  tab->headbuf = buf;
96
 
97
  return  RETURN_OK;
98
  }
99
 
100
 
101
/****** readbasic_head ********************************************************
102
PROTO   void readbasic_head(tabstruct *tab)
103
PURPOSE Read the current FITS header basic keywords.
104
INPUT   pointer to catstruct.
105
OUTPUT  -.
106
NOTES   -.
107
AUTHOR  E. Bertin (IAP)
108
VERSION 25/09/2004
109
 ***/
110
void    readbasic_head(tabstruct *tab)
111
 
112
  {
113
   char         str[88];
114
   char         key[12], name[16],
115
                *filename;
116
   int          i;
117
   KINGSIZE_T   tabsize;
118
 
119
  filename = (tab->cat? tab->cat->filename : strcpy(name, "internal header"));
120
 
121
  if (fitsread(tab->headbuf, "BITPIX  ", &tab->bitpix, H_INT, T_LONG)
122
        ==RETURN_ERROR)
123
    error(EXIT_FAILURE, "*Error*: Corrupted FITS header in ", filename);
124
 
125
  tab->bytepix = tab->bitpix>0?(tab->bitpix/8):(-tab->bitpix/8);
126
 
127
  if (fitsread(tab->headbuf, "NAXIS   ", &tab->naxis, H_INT, T_LONG)
128
        ==RETURN_ERROR)
129
    error(EXIT_FAILURE, "*Error*: Corrupted FITS header in ", filename);
130
 
131
  tabsize = 0;
132
  if (tab->naxis>0)
133
    {
134
    QFREE(tab->naxisn);
135
    QMALLOC(tab->naxisn, int, tab->naxis);
136
/*--get the size of the array*/
137
    tabsize = 1;
138
    for (i=0; i<tab->naxis && i<999; i++)
139
      {
140
      sprintf(key,"NAXIS%-3d", i+1);
141
      if (fitsread(tab->headbuf, key, &tab->naxisn[i], H_INT, T_LONG)
142
                ==RETURN_ERROR)
143
        error(EXIT_FAILURE, "*Error*: incoherent FITS header in ", filename);
144
      tabsize *= tab->naxisn[i];
145
      }
146
    }
147
 
148
/*random groups parameters (optional)*/
149
  tab->pcount = 0;
150
  fitsread(tab->headbuf, "PCOUNT  ", &tab->pcount, H_INT, T_LONG);
151
  tab->gcount = 1;
152
  fitsread(tab->headbuf, "GCOUNT  ", &tab->gcount, H_INT, T_LONG);
153
 
154
/*number of fields (only for tables)*/
155
  tab->tfields = 0;
156
  fitsread(tab->headbuf, "TFIELDS ", &tab->tfields, H_INT, T_LONG);
157
 
158
/*in case of a non-primary header*/
159
  tab->xtension[0] = (char)'\0';
160
  fitsread(tab->headbuf, "XTENSION", tab->xtension, H_STRING, T_STRING);
161
  tab->extname[0] = (char)'\0';
162
  fitsread(tab->headbuf, "EXTNAME ", tab->extname, H_STRING, T_STRING);
163
 
164
  tab->tabsize = tab->bytepix*tab->gcount*((size_t)tab->pcount+tabsize);
165
 
166
/* Scaling parameters for basic FITS integer arrays */
167
  tab->bscale = 1.0;
168
  fitsread(tab->headbuf, "BSCALE ", &tab->bscale, H_FLOAT, T_DOUBLE);
169
  tab->bzero = 0.0;
170
  fitsread(tab->headbuf, "BZERO  ", &tab->bzero, H_FLOAT, T_DOUBLE);
171
  tab->blankflag =
172
    (fitsread(tab->headbuf,"BLANK   ",&tab->blank,H_INT,T_LONG) == RETURN_OK)?
173
        1 : 0;
174
 
175
/* Custom basic FITS parameters */
176
  tab->bitsgn = 1;
177
  fitsread(tab->headbuf, "BITSGN  ", &tab->bitsgn, H_INT, T_LONG);
178
 
179
  if (fitsread(tab->headbuf, "IMAGECOD", str, H_STRING, T_STRING)==RETURN_OK)
180
    {
181
    if (!strcmp(str, "NONE"))
182
      tab->compress_type = COMPRESS_NONE;
183
    else if (!strcmp(str, "BASEBYTE"))
184
      tab->compress_type = COMPRESS_BASEBYTE;
185
    else if (!strcmp(str, "PREV_PIX"))
186
      tab->compress_type = COMPRESS_PREVPIX;
187
    else
188
      warning("Compression skipped: unknown IMAGECOD parameter:", str);
189
    }
190
 
191
/* Checksum */
192
  if (fitsread(tab->headbuf, "DATASUM ", str, H_STRING, T_STRING)==RETURN_OK)
193
    tab->bodysum = (unsigned int)atoi(str);
194
 
195
  return;
196
  }
197
 
198
 
199
/******* readbintabparam_head *************************************************
200
PROTO   int readbintabparam_head(tabstruct *tab)
201
PURPOSE Read the current FITS header parameters concerning the binary-table.
202
INPUT   pointer to tabstruct.
203
OUTPUT  RETURN_OK if a binary table was found and mapped, RETURN_ERROR
204
        otherwise.
205
NOTES   -.
206
AUTHOR  E. Bertin (IAP & Leiden observatory)
207 225 bertin
VERSION 20/07/2010
208 2 bertin
 ***/
209
int     readbintabparam_head(tabstruct *tab)
210
 
211
  {
212
   catstruct    *cat;
213
   keystruct    *key, *prevkey;
214
   char         strf[88], strk[16];
215
   char         *str;
216
   int          naxisn[32];
217
   int          i,j, larray, nfields,narray, pos;
218
 
219
  if (!(cat = tab->cat))
220
    error(EXIT_FAILURE, "*Internal Error*: Table has no parent catalog","!");
221
 
222
/*We are expecting a 2D binary-table, and nothing else*/
223
  if ((tab->naxis != 2)
224
        || (tab->bitpix!=8)
225
        || (tab->tfields == 0)
226
        || strncmp(tab->xtension, "BINTABLE", 8))
227
    return RETURN_ERROR;
228
 
229
/*Size and number of lines in the binary table*/
230
  larray = tab->naxisn[0];
231
  nfields= tab->nkey = tab->tfields;
232
  narray = tab->naxisn[1];
233
 
234
  prevkey = NULL;
235
/*For each of the data fields...*/
236
  pos = 0;
237
  for (i=0; i<nfields; i++)
238
    {
239
/*--manage the chaining of keys*/
240
    QCALLOC(key, keystruct, 1);
241
    if (prevkey)
242
       {
243
       prevkey->nextkey = key;
244
       key->prevkey = prevkey;
245
       }
246
    else
247
       tab->key = key;
248
     prevkey = key;
249
 
250
/*--map binary-table fields*/
251
 
252
    sprintf(strk, "TTYPE%-3d", i+1);
253
    if (fitsread(tab->headbuf, strk, key->name, H_STRING, T_STRING)
254
        != RETURN_OK) {
255
      error(EXIT_FAILURE,
256
        "*Error*: Incorrect FITS binary-table header in ", cat->filename);
257
    }
258
    fitsread(tab->headbuf, strk, key->comment, H_HCOMMENT, T_STRING);
259
 
260
    sprintf(strk, "TUNIT%-3d", i+1);
261
    fitsread(tab->headbuf, strk, key->unit, H_STRING, T_STRING);
262
    sprintf(strk, "TDISP%-3d", i+1);
263
    fitsread(tab->headbuf, strk, key->printf, H_STRING, T_STRING);
264
    if (*key->printf)
265
      tdisptoprintf(key->printf, key->printf);
266
 
267
    sprintf(strk, "TFORM%-3d", i+1);
268
    if (fitsread(tab->headbuf, strk, strf, H_STRING, T_STRING) != RETURN_OK) {
269
      error(EXIT_FAILURE,
270
        "*Error*: Incorrect FITS binary-table header in ", cat->filename);
271
    }
272
    key->pos = pos;
273
    pos += (key->nbytes = tsizeof(strf));
274
    key->ttype = ttypeof(strf);
275
    switch(key->ttype)
276
      {
277
      case T_BYTE:
278
      case T_SHORT:
279
      case T_LONG:
280 215 bertin
      case T_LONGLONG:
281 2 bertin
        key->htype = H_INT;
282
        break;
283
      case T_FLOAT:
284
      case T_DOUBLE:
285
        key->htype = H_EXPO;
286
        break;
287
      case T_STRING:
288
        key->htype = H_STRING;
289
        break;
290
      default:
291 225 bertin
        error(EXIT_FAILURE, "*Error*: Unknown TFORM in ", cat->filename);
292 2 bertin
      }
293
 
294
/*--handle the special case of multimensional arrays*/
295
    if ((naxisn[0] = key->nbytes/t_size[key->ttype]) > 1)
296
      {
297
      sprintf(strk, "TDIM%-3d", i+1);
298
      if (fitsread(tab->headbuf, strk, strf, H_STRING, T_STRING) == RETURN_OK)
299
        {
300
        str = strf;
301
        for (j=0; (naxisn[j]=(int)strtol(str+1, &str, 10)); j++);
302
        key->naxis = j;
303
        }
304
      else
305
        key->naxis = 1;
306
      QMALLOC(key->naxisn, int, key->naxis);
307
      for (j=0; j<key->naxis; j++)
308
        key->naxisn[j] = naxisn[j];
309
      }
310
    else
311
      key->naxis = 0;
312
 
313
    key->nobj = narray;
314
    key->tab = tab;
315
    }
316
 
317
  if (pos != larray)
318
    error(EXIT_FAILURE,
319
        "*Error*: Malformed FITS binary-table header in ", cat->filename);
320
 
321
/*make both ends of the chain meet*/
322
  prevkey->nextkey = tab->key;
323
  tab->key->prevkey = prevkey;
324
 
325
  return RETURN_OK;
326
  }
327
 
328
 
329
/****** update_head ***********************************************************
330
PROTO   int update_head(tabstruct *tab)
331
PURPOSE Update a FITS header according to what's in the table.
332
INPUT   Table structure.
333
OUTPUT  RETURN_OK if tab is a binary table, or RETURN_ERROR otherwise.
334
NOTES   The headbuf pointer in the tabstruct might be reallocated.
335
AUTHOR  E. Bertin (IAP & Leiden observatory)
336 173 bertin
VERSION 11/06/2007
337 2 bertin
 ***/
338
int     update_head(tabstruct *tab)
339
 
340
  {
341
   keystruct    *key;
342
   tabstruct    *ctab;
343
   int          i,j,n,naxis1;
344
   char         strk[88], str[88];
345
   char         *buf;
346
 
347
/*Update EXTNAME, the table name */
348
  if (*tab->extname)
349
    {
350
    addkeywordto_head(tab, "EXTNAME ", "EXTENSION NAME");
351
    fitswrite(tab->headbuf, "EXTNAME ", tab->extname, H_STRING, T_STRING);
352
    }
353
 
354
/* If not a binary table, do only a few basic things */
355
  if ((tab->naxis != 2)
356
        || (tab->bitpix!=8)
357
        || (tab->tfields == 0)
358
        || strncmp(tab->xtension, "BINTABLE", 8))
359
    {
360
    addkeywordto_head(tab, "BITPIX  ", "BITS PER PIXEL");
361
    fitswrite(tab->headbuf, "BITPIX  ", &tab->bitpix, H_INT, T_LONG);
362
    addkeywordto_head(tab, "NAXIS   ", "NUMBER OF AXES");
363
    fitswrite(tab->headbuf, "NAXIS   ", &tab->naxis, H_INT, T_LONG);
364
    for (i=0; i<tab->naxis; i++)
365
      {
366
      sprintf(strk, "NAXIS%-3d", i+1);
367
      addkeywordto_head(tab, strk, "NUMBER OF ELEMENTS ALONG THIS AXIS");
368
      fitswrite(tab->headbuf, strk, &tab->naxisn[i], H_INT, T_LONG);
369
      }
370
    return RETURN_ERROR;
371
    }
372
 
373
/*First, remove all existing TTYPE, TFORM, etc...*/
374 173 bertin
  removekeywordfrom_head(tab, "TTYPE???");
375
  removekeywordfrom_head(tab, "TFORM???");
376
  removekeywordfrom_head(tab, "TUNIT???");
377
  removekeywordfrom_head(tab, "TZERO???");
378
  removekeywordfrom_head(tab, "TSCAL???");
379
  removekeywordfrom_head(tab, "TDIM???");
380
  removekeywordfrom_head(tab, "TDISP???");
381 2 bertin
 
382
 
383
/*Change NAXIS1 in order to take into account changes in width*/
384
  naxis1 = 0;
385
  key = tab->key;
386
  if (tab->nkey>1000) {
387
     for (i=0; i<MIN(999,tab->nkey); i++) {
388
        naxis1 += key->nbytes;
389
        key = key->nextkey;
390
     }
391
     fitswrite(tab->headbuf, "NAXIS1  ", &naxis1, H_INT, T_LONG);
392
  } else {
393
     fitswrite(tab->headbuf, "NAXIS1  ", &tab->naxisn[0], H_INT, T_LONG);
394
  }
395
 
396
/*Change NAXIS1 in the number of fields */
397
  tab->tfields = MIN(999,tab->tfields);
398
  fitswrite(tab->headbuf, "TFIELDS ", &tab->tfields, H_INT, T_LONG);
399
 
400
/*Changes in the number of elements (look for possible segments)*/
401
  for (ctab = tab, n = ctab->naxisn[1];
402
        (ctab=ctab->nexttab) && !ctab->nseg;)
403
    n += ctab->naxisn[1];
404
  fitswrite(tab->headbuf, "NAXIS2  ", &n, H_INT, T_LONG);
405
 
406
  key = tab->key;
407
  if (!key)
408
    return RETURN_ERROR;
409
 
410
  if (tab->nkey>1000)
411
     warning("Too many output keys, trashing the ones bejond 999", "");
412
  for (i=0; i<MIN(999,tab->nkey); i++)
413
    {
414
    sprintf(strk, "TTYPE%-3d", i+1);
415
    addkeywordto_head(tab, strk, key->comment);
416
    fitswrite(tab->headbuf, strk, key->name, H_STRING, T_STRING);
417
    sprintf(strk, "TFORM%-3d", i+1);
418
    addkeywordto_head(tab, strk, "");
419
    tformof(str, key->ttype, key->nbytes/t_size[key->ttype]);
420
    fitswrite(tab->headbuf, strk, str, H_STRING, T_STRING);
421
    if (key->naxis>1)
422
      {
423
       char     *str2, *str2lim;
424
 
425
      sprintf(strk, "TDIM%-3d", i+1);
426
      addkeywordto_head(tab, strk, "");
427
      sprintf(str, "(");
428
      str2 = str+1;
429
      str2lim = str+70; /* Prevent an excessively large string */
430
      for (n=0; n<key->naxis && str2<str2lim; n++)
431
        {
432
        sprintf(str2, n?", %d%n":"%d%n", key->naxisn[n],&j);
433
        str2 += j;
434
        }
435
      sprintf(str2, ")");
436
      fitswrite(tab->headbuf, strk, str, H_STRING, T_STRING);
437
      }
438
    if (*key->unit)
439
      {
440
      sprintf(strk, "TUNIT%-3d", i+1);
441
      addkeywordto_head(tab, strk, "");
442
      fitswrite(tab->headbuf, strk, key->unit, H_STRING, T_STRING);
443
      }
444
    if (*key->printf)
445
      {
446
      sprintf(strk, "TDISP%-3d", i+1);
447
      addkeywordto_head(tab, strk, "");
448
      fitswrite(tab->headbuf, strk, printftotdisp(key->printf, str),
449
                H_STRING, T_STRING);
450
      }
451
    key = key->nextkey;
452
    }
453
 
454
/*Finally re-compute CHECKSUM if present */
455
  if (fitsfind(tab->headbuf, "CHECKSUM")==RETURN_OK)
456
    {
457
    unsigned int        sum;
458
 
459
    if (tab->bodysum)
460
      {
461
      sprintf(str, "%u", tab->bodysum);
462
      fitswrite(tab->headbuf, "DATASUM ", str, H_STRING, T_STRING);
463
      }
464
    sum = tab->bodysum;
465
/*-- Now the header */
466
    buf = tab->headbuf;
467
    for (i=tab->headnblock; i--; buf+=FBSIZE)
468
      sum = compute_blocksum(buf, sum);
469
/*-- Complement to 1 */
470
    encode_checksum(~sum, str);
471
    fitswrite(tab->headbuf, "CHECKSUM", str, H_STRING, T_STRING);
472
    }
473
 
474
/*That may be enough for now; to be continued...*/
475
 
476
  return RETURN_OK;
477
  }
478
 
479
 
480
/****** prim_head *************************************************************
481
PROTO   int prim_head(tabstruct *tab)
482
PURPOSE Update a FITS header to make it "primary" (not extension)
483
INPUT   Table structure.
484
OUTPUT  RETURN_OK if tab header was already primary, or RETURN_ERROR otherwise.
485
NOTES   -.
486 173 bertin
AUTHOR  E. Bertin (IAP & Leiden observatory) C. Marmo (IAP)
487
VERSION 11/06/2007
488 2 bertin
 ***/
489
int     prim_head(tabstruct *tab)
490
 
491
  {
492
  if (!tab->headbuf)
493
    return RETURN_ERROR;
494
  if (!strncmp(tab->headbuf, "XTENSION",8))
495
      {
496
      strncpy(tab->headbuf, "SIMPLE  =                    T  "
497
        "/ This is a FITS file                            ", 80);
498 173 bertin
/* fitsverify 4.13 (CFITSIO V3.002) return an error
499
   if PCOUNT and GCOUNT are in a primary header (23/05/2007)*/
500
      removekeywordfrom_head(tab, "PCOUNT");
501
      removekeywordfrom_head(tab, "GCOUNT");
502 2 bertin
      return RETURN_ERROR;
503
      }
504 173 bertin
 
505 2 bertin
  return RETURN_OK;
506
  }
507
 
508
 
509
/****** ext_head *************************************************************
510
PROTO   int ext_head(tabstruct *tab)
511
PURPOSE Update a FITS header to make it "extension" (not primary)
512
INPUT   Table structure.
513
OUTPUT  RETURN_OK if tab header was already extension, or RETURN_ERROR
514
        otherwise.
515
NOTES   -.
516 173 bertin
AUTHOR  E. Bertin (IAP & Leiden observatory) C. Marmo (IAP)
517
VERSION 20/06/2007
518 2 bertin
 ***/
519
int     ext_head(tabstruct *tab)
520
 
521
  {
522
  if (!tab->headbuf)
523
    return RETURN_ERROR;
524
  if (!strncmp(tab->headbuf, "SIMPLE  ",8))
525
      {
526
      strncpy(tab->headbuf, "XTENSION= 'IMAGE   '           "
527
                "/ Image extension                                ", 80);
528 173 bertin
/* fitsverify 4.13 (CFITSIO V3.002) return an error
529
   if EXTEND are in an extension header (20/06/2007)*/
530
      removekeywordfrom_head(tab, "EXTEND");
531
/* fitsverify 4.13 (CFITSIO V3.002) return an error
532
   if PCOUNT and GCOUNT are not in the extension header (23/05/2007) */
533
      addkeywordto_head(tab, "PCOUNT  ", "required keyword; must = 0");
534
      addkeywordto_head(tab, "GCOUNT  ", "required keyword; must = 1");
535
      fitswrite(tab->headbuf,"PCOUNT  ", &tab->pcount, H_INT, T_LONG);
536
      fitswrite(tab->headbuf,"GCOUNT  ", &tab->gcount, H_INT, T_LONG);
537 2 bertin
      return RETURN_ERROR;
538
      }
539
 
540
  return RETURN_OK;
541
  }
542
 
543
 
544
/****** addkeyto_head *********************************************************
545
PROTO   int addkeyto_head(tabstruct *tab, keystruct *key)
546
PURPOSE Add a keyword and its value to a table header.
547
INPUT   Table structure,
548
        Key containing the keyword and its value.
549
OUTPUT  Line position in the FITS header.
550
NOTES   The headbuf pointer in the tabstruct might be reallocated.
551
        Pre-existing keywords are overwritten (but not their comments).
552
AUTHOR  E. Bertin (IAP & Leiden observatory)
553
VERSION 11/05/2002
554
 ***/
555
int     addkeyto_head(tabstruct *tab, keystruct *key)
556
 
557
  {
558
   int  n;
559
 
560
  n = addkeywordto_head(tab, key->name, key->comment);
561
  fitswrite(tab->headbuf, key->name, key->ptr, key->htype, key->ttype);
562
 
563
  return n;
564
  }
565
 
566
 
567
/****** addkeywordto_head *****************************************************
568
PROTO   int addkeywordto_head(tabstruct *tab, char *keyword, char *comment)
569
PURPOSE Add a keyword and a comment to a table header.
570
INPUT   Table structure,
571
        String containing the keyword,
572
        String containing the comment.
573
OUTPUT  Line position in the FITS header.
574
NOTES   The headbuf pointer in the tabstruct might be reallocated.
575
        Pre-existing keywords are overwritten (but not their comments).
576
AUTHOR  E. Bertin (IAP & Leiden observatory)
577
VERSION 21/04/2003
578
 ***/
579
int     addkeywordto_head(tabstruct *tab, char *keyword, char *comment)
580
 
581
  {
582
   int  n;
583
 
584
  if ((fitsfind(tab->headbuf, keyword) == RETURN_ERROR
585
        || findkey(keyword, (char *)histokeys, 12)!=RETURN_ERROR)
586
        && (fitsfind(tab->headbuf, "END     ")+1)*80 >= tab->headnblock*FBSIZE)
587
    {
588
    tab->headnblock++;
589
    QREALLOC(tab->headbuf, char, tab->headnblock*FBSIZE);
590
    memset(tab->headbuf + (tab->headnblock-1)*FBSIZE, ' ', FBSIZE);
591
    }
592
 
593
  n = fitsadd(tab->headbuf, keyword, comment);
594
 
595
  return n;
596
  }
597
 
598
 
599 173 bertin
/****** removekeywordfrom_head ************************************************
600
PROTO   int removekeywordfrom_head(tabstruct *tab, char *keyword)
601
PURPOSE Remove a keyword from a table header.
602
INPUT   Table structure,
603
        String containing the keyword.
604
OUTPUT  RETURN_OK if the keyword was found, RETURN_ERROR otherwise..
605
NOTES   The headbuf pointer in the tabstruct might be reallocated.
606
        '?' wildcard allowed; Don't remove the ``END'' keyword with this!!!
607
AUTHOR  E. Bertin (IAP)
608
VERSION 11/06/2007
609
 ***/
610
int     removekeywordfrom_head(tabstruct *tab, char *keyword)
611
 
612
  {
613
   int  nb;
614
 
615
  if (fitsremove(tab->headbuf, keyword) == RETURN_OK)
616
    {
617
    if ((nb=fitsfind(tab->headbuf, "END     ")/(FBSIZE/80)+1) < tab->headnblock)
618
      {
619
      tab->headnblock = nb;
620
      QREALLOC(tab->headbuf, char, tab->headnblock*FBSIZE);
621
      }
622
    return RETURN_OK;
623
    }
624
  else
625
    return RETURN_ERROR;
626
  }
627
 
628
 
629 2 bertin
/****** tformof ***************************************************************
630
PROTO   int tformof(char *str, t_type ttype, int n)
631
PURPOSE Return the ``TFORM'' string corresponding to a t_type
632
        and the number of elements.
633
INPUT   a char pointer (to be filled with the T_FORM string),
634
        t_type,
635
        Number of elements.
636
OUTPUT  RETURN_OK if everything went as expected, or RETURN_ERROR otherwise.
637
NOTES   -.
638
AUTHOR  E. Bertin (IAP & Leiden observatory)
639 215 bertin
VERSION 28/10/2009
640 2 bertin
 ***/
641
int     tformof(char *str, t_type ttype, int n)
642
 
643
  {
644
   char t;
645
 
646
  switch (ttype)
647
    {
648
    case T_BYTE:        t = 'B';
649
                        break;
650
    case T_SHORT:       t = 'I';
651
                        break;
652
    case T_LONG:        t = 'J';
653
                        break;
654 215 bertin
    case T_LONGLONG:    t = 'K';
655
                        break;
656 2 bertin
    case T_FLOAT:       t = 'E';
657
                        break;
658
    case T_DOUBLE:      t = 'D';
659
                        break;
660
    case T_STRING:      t = 'A';
661
                        break;
662
    default:            return  RETURN_ERROR;
663
    }
664
 
665
  sprintf(str, "%d%c", n, t);
666
 
667
  return RETURN_OK;
668
  }
669
 
670
 
671
/****** tsizeof ***************************************************************
672
PROTO   int tsizeof(char *str)
673
PURPOSE Return the size of a binary-table field from its ``TFORM''.
674
INPUT   TFORM string (see the FITS documentation).
675
OUTPUT  size in bytes, or RETURN_ERROR if the TFORM is unknown.
676
NOTES   -.
677
AUTHOR  E. Bertin (IAP & Leiden observatory)
678 215 bertin
VERSION 28/10/2009
679 2 bertin
 ***/
680
int     tsizeof(char *str)
681
 
682
  {
683
   int  n;
684
   char *str2;
685
 
686
  str2 = str;
687
  if (!(n = strtol(str, &str2, 10)))
688
    n = 1;
689
 
690
  switch ((int)*str2)
691
    {
692 215 bertin
    case 'L': case 'B': case 'A':               return  n;
693
    case 'X':                                   return  (n-1)/8+1;
694
    case 'I':                                   return  2*n;
695
    case 'J': case 'E':                         return  4*n;
696
    case 'C': case 'D': case 'K': case 'P':     return  8*n;
697
    case 'M':                                   return  16*n;
698
    default:                                    return  RETURN_ERROR;
699 2 bertin
    }
700
 
701
  }
702
 
703
 
704
/****** ttypeof ***************************************************************
705
PROTO   t_type ttypeof(char *str)
706
PURPOSE Give the ``t_type'' of a binary-table field from its ``TFORM''.
707
INPUT   TFORM string (see the FITS documentation).
708
OUTPUT  size in bytes, or RETURN_ERROR if the TFORM is unknown.
709
NOTES   -.
710
AUTHOR  E. Bertin (IAP & Leiden observatory)
711 215 bertin
VERSION 28/10/2009
712 2 bertin
 ***/
713
t_type  ttypeof(char *str)
714
 
715
  {
716
   char *str2;
717
 
718
  str2 = str;
719
  strtol(str, &str2, 10);
720
  switch ((int)*str2)
721
    {
722
    case 'L': case 'B': case 'X':       return  T_BYTE;
723
    case 'I':                           return  T_SHORT;
724
    case 'J':                           return  T_LONG;
725 215 bertin
    case 'K':                           return  T_LONGLONG;
726 2 bertin
    case 'E':                           return  T_FLOAT;
727
    case 'D':                           return  T_DOUBLE;
728
    case 'A':                           return  T_STRING;
729
    default:                            return  (t_type)RETURN_ERROR;
730
    }
731
 
732
  }
733
 
734
 
735
/****** tdisptoprintf *********************************************************
736
PROTO   char    *tdisptoprintf(char *tdisp, char *str)
737
PURPOSE Convert the ``TDISP'' FITS format to the printf() format.
738
INPUT   TDISP format string (see the FITS documentation),
739
        output string (allocated pointer).
740
OUTPUT  printf() format string (see e.g.  K&R).
741
NOTES   The present conversion does not handle binary or engineer notations.
742
        A NULL vector is returned if the conversion was unsuccessful.
743
AUTHOR  E. Bertin (IAP & Leiden observatory)
744
VERSION 25/09/2004
745
 ***/
746
char    *tdisptoprintf(char *tdisp, char *str)
747
 
748
  {
749
   char         control[4];
750
   int          w,d, n;
751
 
752
  w = d = 0;
753
  n = 0;
754
  n=sscanf(tdisp,"%[ALIBOZFENSGD]%d.%d", control, &w, &d)-1;
755
  if (!w)
756
    {
757
    warning("Strange TDISP format: ", tdisp);
758
    return NULL;
759
    }
760
  switch ((int)*control)
761
    {
762
    case 'A':
763
      sprintf(str, "%%%dc",w);
764
      break;
765
    case 'L':
766
      sprintf(str, "%%%dd",w);
767
      break;
768
    case 'I':
769
      if (n>1)
770
        sprintf(str, "%%%d.%dd",w,d);
771
      else
772
        sprintf(str, "%%%dd",w);
773
      break;
774
    case 'B': case 'Z':
775
      if (n>1)
776
        sprintf(str, "%%%d.%dx",w,d);
777
      else
778
        sprintf(str, "%%%dx",w);
779
      break;
780
    case 'O':
781
      if (n>1)
782
        sprintf(str, "%%%d.%do",w,d);
783
      else
784
        sprintf(str, "%%%do",w);
785
      break;
786
    case 'F':
787
      if (n>1)
788
        sprintf(str, "%%%d.%df",w,d);
789
      else
790
        sprintf(str, "%%%df",w);
791
      break;
792
    case 'E': case 'D':
793
      if (n>1)
794
        sprintf(str, "%%%d.%dE",w,d);
795
      else
796
        sprintf(str, "%%%dE",w);
797
      break;
798
    case 'G':
799
      if (n>1)
800
        sprintf(str, "%%%d.%dG",w,d);
801
      else
802
        sprintf(str, "%%%dG",w);
803
      break;
804
    default:
805
      warning("Unknown TDISP format: ", tdisp);
806
      return NULL;
807
    }
808
 
809
  return str;
810
  }
811
 
812
 
813
/****** printftotdisp *********************************************************
814
PROTO   char    *printftotdisp(char *tdisp, char *str)
815
PURPOSE Convert the printf() format to the ``TDISP'' FITS format.
816
INPUT   printf() format string (see e.g.  K&R),
817
        output string (allocated pointer).
818
OUTPUT  TDISP format string (see the FITS documentation).
819
NOTES   The handling of C string formatting does not include the precision.
820
        NULL is returned in case of unsucessful conversion.
821
AUTHOR  E. Bertin (IAP & Leiden observatory)
822
VERSION 25/09/2004
823
 ***/
824
char    *printftotdisp(char *cprintf, char *str)
825
 
826
  {
827
   char         *control;
828
   int          w,d,n;
829
 
830
  *str = 0;
831
  w = d = 0;
832
  if (!(control = strpbrk(cprintf, "cdueERfFgGoOxXs")))
833
    {
834
    warning("Unknown printf() format: ", cprintf);
835
    return NULL;
836
    }
837
 
838
  n = sscanf(cprintf,"%%%d.%d", &w, &d);
839
  w = abs(w);
840
  if (!n)
841
    {
842
    warning("Unconvertible printf() format: ", cprintf);
843
    return NULL;
844
    }
845
 
846
  switch ((int)*control)
847
    {
848
    case 'c':
849
      sprintf(str, "A%d",w);
850
      break;
851
    case 's':
852
      sprintf(str, "A%d",w);
853
      break;
854
    case 'd': case 'u':
855
      if (n>1)
856
        sprintf(str, "I%d.%d",w,d);
857
      else
858
        sprintf(str, "I%d",w);
859
      break;
860
    case 'o': case 'O':
861
      if (n>1)
862
        sprintf(str, "O%d.%d",w,d);
863
      else
864
        sprintf(str, "O%d",w);
865
      break;
866
    case 'x': case 'X':
867
      if (n>1)
868
        sprintf(str, "Z%d.%d",w,d);
869
      else
870
        sprintf(str, "Z%d",w);
871
      break;
872
    case 'f': case 'F':
873
      if (n>1)
874
        sprintf(str, "F%d.%d",w,d);
875
      else
876
        sprintf(str, "F%d",w);
877
      break;
878
    case 'e': case 'E':
879
      if (n>1)
880
        sprintf(str, "E%d.%d",w,d);
881
      else
882
        sprintf(str, "E%d",w);
883
      break;
884
    case 'g': case 'G':
885
      if (n>1)
886
        sprintf(str, "G%d.%d",w,d);
887
      else
888
        sprintf(str, "G%d",w);
889
      break;
890
    default:
891
      warning("Unknown printf() format: ", cprintf);
892
      return NULL;
893
    }
894
 
895
  return str;
896
  }
897