public software.sextractor

[/] [trunk/] [src/] [fits/] [fitsutil.c] - Blame information for rev 173

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

Line No. Rev Author Line
1 2 bertin
/*
2
                                fitsutil.c
3
 
4
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5
*
6
*       Part of:        The LDAC Tools
7
*
8
*       Author:         E.BERTIN, DeNIS/LDAC
9
*
10
*       Contents:       functions for handling FITS keywords.
11
*
12 173 bertin
*       Last modify:    12/06/2007
13 2 bertin
*
14
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15
*/
16
 
17
#ifdef HAVE_CONFIG_H
18
#include        "config.h"
19
#endif
20
 
21
#include        <stdio.h>
22
#include        <stdlib.h>
23
#include        <string.h>
24
 
25
#include        "fitscat_defs.h"
26
#include        "fitscat.h"
27
 
28
char    histokeys[][12] = {"COMMENT ", "HISTORY ", "        ", ""};
29
 
30
/****** fitsadd ***************************************************************
31
PROTO   int fitsadd(char *fitsbuf, char *keyword, char *comment)
32
PURPOSE Write a FITS keyword in a fits header.
33
INPUT   pointer to the FITS buffer,
34
        name of the keyword to be created,
35
        a comment to put beyond the slash, or next to a COMMENT or HISTORY.
36
OUTPUT  line position or RETURN_ERROR if the keyword is invalid.
37
NOTES   For all keywords except commentary ones (like COMMENT, HISTORY or
38
        blank), it is checked that they do not exist already.
39
        Enough memory should be provided for the FITS header to contain one
40
        more line of 80 char.
41 173 bertin
AUTHOR  E. Bertin (IAP & Leiden observatory) C. Marmo (IAP)
42
VERSION 13/06/2007
43 2 bertin
 ***/
44
int     fitsadd(char *fitsbuf, char *keyword, char *comment)
45
 
46
  {
47
   char         *key_ptr;
48
   char         str[82];
49
   int          headpos, headpos2, commentflag,
50
                i, n;
51
 
52
 
53
  if (strcspn(keyword, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 -_"))
54
    return RETURN_ERROR;
55
  commentflag = findkey(keyword, (char *)histokeys, 12)==RETURN_ERROR?0:1;
56
  if (commentflag || (headpos = fitsfind(fitsbuf, keyword))==RETURN_ERROR)
57
    {
58
    headpos2 = headpos = fitsfind(fitsbuf, "END     ");
59
/*-- Special case of NAXIS parameters */
60
    if (!strncmp(keyword, "NAXIS", 5) && keyword[5] && keyword[5] != ' ')
61
      {
62
      sscanf(keyword, "NAXIS%d", &n);
63
/*---- Look for all previous NAXIS parameters */
64
      for (i=n; i--;)
65
        {
66
        sprintf(str, "NAXIS%-3d", i);
67
        headpos=fitsfind(fitsbuf, str);
68
        if (headpos>0)
69
          break;
70
        }
71
      if (headpos<0)
72
/*---- Most likely keyword is NAXIS1 */
73
        headpos=fitsfind(fitsbuf, "NAXIS   ");
74
      if (headpos>0)
75
        headpos++;
76
      else
77
        return RETURN_ERROR;
78
      }
79 173 bertin
/*-- Special case of PCOUNT/GCOUNT parameters */
80
    if (!strncmp(keyword, "PCOUNT", 6))
81
      {
82
      headpos=fitsfind(fitsbuf, "NAXIS   ");
83
      sscanf(fitsbuf+80*headpos, "NAXIS   =                    %d", &n);
84
      if (headpos>0)
85
        headpos+=(n+1);
86
      else
87
        return RETURN_ERROR;
88
      }
89
    if (!strncmp(keyword, "GCOUNT", 6))
90
      {
91
      headpos=fitsfind(fitsbuf, "NAXIS   ");
92
      sscanf(fitsbuf+80*headpos, "NAXIS   =                    %d", &n);
93
      if (headpos>0)
94
        headpos+=(n+2);
95
      else
96
        return RETURN_ERROR;
97
      }
98
 
99 2 bertin
    key_ptr = fitsbuf+80*headpos;
100
    memmove(key_ptr+80, key_ptr, 80*(headpos2-headpos+1));
101
 
102
    if (commentflag)
103
      sprintf(str, "%-8.8s %-71.71s",
104
        keyword, comment?comment:" ");
105
    else if (comment && *comment)
106
      sprintf(str, "%-8.8s=                      / %-47.47s",
107
        keyword, comment);
108
    else
109
      sprintf(str, "%-8.8s=                        %-47.47s",
110
              keyword, " ");
111
    memcpy(key_ptr, str, 80);
112
    }
113
 
114
  return headpos;
115
  }
116
 
117
 
118
/****** fitsfind **************************************************************
119
PROTO   int fitsfind(char *fitsbuf, char *keyword)
120
PURPOSE Search for a FITS keyword in a FITS header.
121
INPUT   pointer to the FITS buffer,
122
        name of the keyword to search for.
123
OUTPUT  position in lines  of 80 char (0=first) of the keyword if it was
124
        found, RETURN_ERROR otherwise.
125
NOTES   The buffer MUST contain the ``END     '' keyword.
126
AUTHOR  E. Bertin (IAP & Leiden observatory)
127
VERSION 15/02/96
128
 ***/
129
int     fitsfind(char *fitsbuf, char *keyword)
130
 
131
  {
132
   char *ptr;
133
   int  i, len;
134
 
135
  len = strlen(keyword);
136
  for (i=0; strncmp(ptr=&fitsbuf[80*i], "END     ", 8); i++)
137
    if (!wstrncmp(ptr, keyword, len))
138
      return i;
139
  if (strncmp(keyword, "END     ", 8))
140
    return RETURN_ERROR;
141
  else
142
    return i;
143
  }
144
 
145
 
146
/****** fitsnfind *************************************************************
147
PROTO   char    *fitsnfind(char *fitsbuf, char *str, int nblock)
148
PURPOSE Search for a FITS keyword in a fits header of nblock blocks.
149
INPUT   pointer to the FITS buffer,
150
        name of the keyword to search for,
151
        number of FITS blocks (2880 bytes each).
152
OUTPUT  pointer at the keyword position if it was found, NULL otherwise.
153
NOTES   No need for an ``END     '' keyword.
154
AUTHOR  E. Bertin (IAP & Leiden observatory)
155
VERSION 25/04/97
156
 ***/
157
char    *fitsnfind(char *fitsbuf, char *str, int nblock)
158
  {
159
   int  i;
160
 
161
  for (i=36*nblock;i--; fitsbuf+=80)
162
    if (!strncmp(fitsbuf, str, strlen(str)))
163
      return fitsbuf;
164
 
165
  return        (char *)NULL;
166
  }
167
 
168
 
169
/****** fitspick **************************************************************
170
PROTO   int fitspick(char *fitsline, char *keyword, void *ptr, h_type *htype,
171
                        t_type *ttype, char *comment)
172
 
173
PURPOSE Pick up FITS keyword,content,type and comment in a fits header line.
174
INPUT   pointer to the current line of FITS buffer,
175
        pointer to a char * (where to put the keyword),
176
        pointer to ``where to put the data'',
177
        pointer to ``where to put the h_type'',
178
        pointer to ``where to put the t_type'',
179
        pointer to a char * (where to put the comment).
180
OUTPUT  RETURN_OK if something was found, RETURN_ERROR otherwise.
181
NOTES   -.
182
AUTHOR  E. Bertin (IAP),
183
        E.R. Deul - Handling of NaN
184 173 bertin
VERSION 04/06/2007
185 2 bertin
 ***/
186
int     fitspick(char *fitsline, char *keyword, void *ptr, h_type *htype,
187
                t_type *ttype, char *comment)
188
 
189
  {
190
   char *fptr, *cptr, c, *lastspace;
191
   int  i,j, toggle;
192
 
193
  *((char *)ptr) = 0;
194
/*First, get the keyword*/
195
  memcpy(keyword, fitsline, 8);
196
  keyword[8] = 0;
197
 
198
/*Handle comments*/
199
  if ((int)fitsline[8] != '=')
200
    {
201
    if (strncmp(keyword, "COMMENT ", 8)
202
        && strncmp(keyword, "HISTORY ", 8)
203
        && strncmp(keyword, "HIERARCH", 8)
204
        && strncmp(keyword, "        ", 8))
205
      return RETURN_ERROR;
206
    memcpy(comment, fitsline+9, 71);
207
    comment[71] = 0;
208
    *htype = H_COMMENT;
209
    *ttype = T_STRING;
210
    return RETURN_OK;
211
    }
212
 
213
  for (j=10; j<80 && fitsline[j] == (char)' '; j++);
214
  if (j==80 || fitsline[j] == '/')
215
    {
216
    *htype = H_COMMENT;
217
    *ttype = T_STRING;
218
    return RETURN_ERROR;
219
    }
220
  if ((int)fitsline[j] == '\'')
221
    {
222
    cptr = ptr;
223
    for (fptr = fitsline + (i=j+1); i<80; i++)
224
      {
225
      if (*fptr==(char)'\'')
226
        {
227
        if (i++>=79 || *(fptr+1)!=(char)'\'')
228
          break;
229
        else
230
          fptr++;
231
        }
232
      *cptr++ = *fptr++;
233
      }
234
    *cptr = 0;
235
/*-- Check if there is a trailing space */
236
    *htype = (cptr != ptr && *(cptr-1)==' ') ? H_STRINGS: H_STRING;
237
    *ttype = T_STRING;
238
    }
239
  else if (fitsline[j] == (char)'T' || fitsline[j] == (char)'F')
240
    {
241
    *((BYTE *)ptr) = fitsline[j]==(char)'T'?1:0;
242
    *htype = H_BOOL;
243
    *ttype = T_BYTE;
244
    }
245
  else if (!strncmp(fitsline+j, "NaN", 3))
246
    {
247
    *((double *)ptr) = BIG;
248
    *htype = H_EXPO;
249
    *ttype = T_DOUBLE;
250
    }
251
  else
252
    {
253
    for (i=j; i<80 && fitsline[i]!=(char)'/' && fitsline[i]!=(char)'.'; i++);
254
/*-- Handle floats*/
255 173 bertin
    if (fitsline[i]==(char)'.')
256 2 bertin
      {
257 22 bertin
      fixexponent(fitsline);
258 2 bertin
      *((double *)ptr) = atof(fitsline+j);
259
      *htype = H_EXPO;
260
      *ttype = T_DOUBLE;
261
      }
262
    else
263
/*---- Handle ints*/
264
      {
265
      *((int *)ptr) = atoi(fitsline+j);
266
      *htype = H_INT;
267
      *ttype = T_LONG;
268
      }
269
    }
270
 
271
/*Store comment if it is found*/
272
  toggle = 0;
273
  lastspace = NULL;
274
  for (fptr = fitsline + (i=j); i<80; i++)
275
    {
276
    if (*fptr == (char)'\'')
277
      toggle^=toggle;
278
    if (*(fptr++) == (char)'/' && !toggle)
279
      {
280
      while (++i<80 && *fptr<=' ')
281
        fptr++;
282
      i--;
283
      while (++i<80)
284
        if ((c=*(fptr++))>= ' ')
285
          {
286
          *(comment++) = c;
287
          if (c>' ')
288
            lastspace = comment;
289
          }
290
      }
291
    }
292
  if (lastspace)
293
    *lastspace = '\0';
294
  else
295
    *comment = '\0';
296
 
297
  return RETURN_OK;
298
  }
299
 
300
 
301
/****** fitsread **************************************************************
302
PROTO   int fitsread(char *fitsbuf, char *keyword, void *ptr, h_type htype,
303
                        t_type ttype)
304
PURPOSE Read a FITS keyword in a fits header.
305
INPUT   pointer to the FITS buffer,
306
        name of the keyword to be read,
307
        pointer where to put the read data,
308
        h_type of the data to be read (see fitscat.h),
309
        t_type of the data to be read (see fitscat.h).
310
OUTPUT  RETURN_OK if the keyword was found, RETURN_ERROR otherwise.
311
NOTES   The buffer MUST contain the ``END     '' keyword.
312
AUTHOR  E. Bertin (IAP & Leiden observatory)
313
VERSION 04/08/2004
314
 ***/
315
int     fitsread(char *fitsbuf, char *keyword, void *ptr, h_type htype,
316
                t_type ttype)
317
 
318
  {
319
   int          i,pos;
320
   char         s[4], str[82];
321
   char         *st, *st2;
322
 
323
  if ((pos = fitsfind(fitsbuf, keyword)) < 0)
324
    return RETURN_ERROR;
325
 
326
  strncpy(str,fitsbuf+80*pos,80);
327
  str[80] = '\0';
328
 
329
  switch(htype)
330
    {
331
    case H_INT:         if (ttype == T_SHORT)
332
                          sscanf(str+10, "    %hd", (short *)ptr);
333
                        else
334
                          sscanf(str+10, "    %d", (LONG *)ptr);
335
                        break;
336
 
337
    case H_FLOAT:
338
    case H_EXPO:        fixexponent(str);
339
                        if (ttype == T_DOUBLE)
340
                          sscanf(str+10, "    %lf", (double *)ptr);
341
                        else
342
                          sscanf(str+10, "    %f", (float *)ptr);
343
                        break;
344
 
345
    case H_BOOL:        sscanf(str+10, "%1s", s);
346
                        if (ttype == T_BYTE)
347
                          *(BYTE *)ptr = ((int)s[0] == 'T') ? 1 : 0;
348
                        else if (ttype == T_SHORT)
349
                          *(short *)ptr = ((int)s[0] == 'T') ? 1 : 0;
350
                        else
351
                          *(LONG *)ptr = ((int)s[0] == 'T') ? 1 : 0;
352
                        break;
353
 
354
    case H_STRING:      st = ptr;
355
                        st2= str+10;
356
                        for (i=70; i-- && *(st2++)!=(char)'\'';);
357
                        while (i-->0)
358
                          {
359
                          if (*st2 == '\'' && *(++st2) != '\'')
360
                            break;
361
                          *(st++) = *(st2++);
362
                          }
363
                        do
364
                          {
365
                          *(st--) = (char)'\0';
366
                          } while (st>(char *)ptr && (*st == (char)' '));
367
                        break;
368
 
369
    case H_STRINGS:     st = ptr;
370
                        st2= str+10;
371
                        for (i=70; i-- && *(st2++)!=(char)'\'';);
372
                        while (i-->0)
373
                          {
374
                          if (*st2 == '\'' && *(++st2) != '\'')
375
                            break;
376
                          *(st++) = *(st2++);
377
                          }
378
                        *st = (char)'\0';
379
                        break;
380
 
381
    case H_COMMENT:     strcpy(ptr,str+9);
382
                        break;
383
 
384
    case H_HCOMMENT:    strcpy(ptr,str+33);
385
                        break;
386
 
387
    default:            error(EXIT_FAILURE,
388
                                "*Internal Error*: Unknown FITS type in ",
389
                                "fitsread()");
390
                        break;
391
    }
392
 
393
  return RETURN_OK;
394
  }
395
 
396
 
397
/****** fitsremove ************************************************************
398
PROTO   int fitsremove(char *fitsbuf, char *keyword)
399
PURPOSE Remove one (or more) FITS keyword from a fits header.
400
INPUT   pointer to the FITS buffer,
401
        name of the keyword to be created.
402
OUTPUT  RETURN_OK if the keyword was found, RETURN_ERROR otherwise.
403
NOTES   '?' wildcard allowed;
404
        Don't remove the ``END'' keyword with this!!!
405
AUTHOR  E. Bertin (IAP & Leiden observatory)
406
VERSION 08/04/99
407
 ***/
408
 
409
int     fitsremove(char *fitsbuf, char *keyword)
410
 
411
  {
412
   char *cp1,*cp2;
413
   int  endpos,pos, i,n;
414
 
415
  endpos = fitsfind(fitsbuf, "END     ");
416
  for (n=0; (pos = fitsfind(fitsbuf, keyword))>=0; n++, endpos--)
417
    for (cp1=fitsbuf+80*(pos+1), cp2=fitsbuf+80*pos, i=80*(endpos - pos); i--;)
418
      *(cp2++) = *(cp1++);
419
 
420
  if (!n)
421
    return RETURN_ERROR;
422
 
423
  memset(fitsbuf+80*(endpos+1), ' ', 80*n);
424
 
425
  return RETURN_OK;
426
  }
427
 
428
 
429
/****** fitswrite *************************************************************
430
PROTO   int fitswrite(char *fitsbuf, char *keyword, void *ptr, h_type htype,
431
                        t_type ttype)
432
PURPOSE Write a FITS keyword in a fits header.
433
INPUT   pointer to the FITS buffer,
434
        name of the keyword to be written,
435
        pointer where to retrieve the  data,
436
        h_type of the data to be written (see fitscat.h),
437
        t_type of the data to be written (see fitscat.h).
438
OUTPUT  RETURN_OK if the keyword was found, RETURN_ERROR otherwise.
439
NOTES   The buffer MUST contain the ``END     '' keyword.
440
        The keyword must already exist in the buffer (use fitsadd()).
441
AUTHOR  E. Bertin (IAP & Leiden observatory)
442 22 bertin
VERSION 21/09/2006
443 2 bertin
 ***/
444
int     fitswrite(char *fitsbuf, char *keyword, void *ptr, h_type htype,
445
                t_type ttype)
446
 
447
  {
448
   int          i, l, pos, posoff, flag;
449
   char         str[81],str2[81];
450
   char         *cstr, *cstr1,*cstr2,
451
                c;
452
 
453
/* Ignore HISTORY and COMMENTS */
454
  if (findkey(keyword, (char *)histokeys, 12)!=RETURN_ERROR
455
        || (pos = fitsfind(fitsbuf, keyword)) < 0)
456
    return RETURN_ERROR;
457
  posoff = 10;
458
  fitsbuf += 80*pos;
459
  switch(htype)
460
    {
461
    case H_INT: sprintf(str, "%20d", (ttype==T_SHORT)?
462
                                *(short *)ptr: *(int *)ptr);
463
                        break;
464
 
465
    case H_FLOAT:       sprintf(str, "        %12.4f", (ttype==T_DOUBLE)?
466
                                *(double *)ptr: *(float *)ptr);
467
                        break;
468
 
469
    case H_EXPO:        sprintf(str, "    %16.9E", (ttype==T_DOUBLE)?
470
                                *(double *)ptr: *(float *)ptr);
471
                        break;
472
 
473 22 bertin
    case H_BOOL:        if ((ttype==T_SHORT)? *(short *)ptr :
474
                                ((ttype==T_BYTE)? *(BYTE *)ptr : *(LONG *)ptr))
475 2 bertin
                          sprintf(str, "                   T");
476
                        else
477
                          sprintf(str, "                   F");
478
                        break;
479
 
480
    case H_STRING:      /* Handle the famous quote */
481
                        cstr1 = (char *)ptr;
482
                        cstr2 = str2;
483
                        for (i=0; i<80; i++)
484
                          if (!(c=*(cstr2++) = *(cstr1++)))
485
                            break;
486
                          else if (c == '\'')
487
                            {
488
                            *(cstr2++) = '\'';
489
                            i++;
490
                            }
491
                        if (strlen(str2)<=18)
492
                          {
493
                          sprintf(str, "'%-18.18s ", str2);
494
                          cstr = str+18;
495
                          i = 10;
496
                          }
497
                        else
498
                          {
499
                          sprintf(str, "'%-68.68s ", str2);
500
                          cstr = str+68;
501
                          i = 60;
502
                          }
503
                        for (; i-- && *cstr==(char)' '; cstr--);
504
                        *(++cstr) = (char)'\'';
505
                        if (i>9)
506
                          *(++cstr) = 0;
507
                        break;
508
 
509
    case H_STRINGS:     /* Handle the famous quote */
510
                        cstr1 = (char *)ptr;
511
                        cstr2 = str2;
512
                        for (i=0; i<80; i++)
513
                          if (!(c=*(cstr2++) = *(cstr1++)))
514
                            break;
515
                          else if (c == '\'')
516
                            {
517
                            *(cstr2++) = '\'';
518
                            i++;
519
                            }
520
                        sprintf(str, "'%s'", str2);
521
                        for (i+=2;i<20; i++)
522
                          str[i]=' ';
523
                        str[i] = '\0';
524
                        break;
525
 
526
    case H_COMMENT:     sprintf(str, "%-70s", (char *)ptr);
527
                        posoff = 9;
528
                        break;
529
 
530
                        /* Special case of ``half-comments'' */
531
    case H_HCOMMENT:    sprintf(str, " / %-47s", (char *)ptr);
532
                        posoff = 30;
533
                        break;
534
 
535
    default:            error(EXIT_FAILURE,
536
                                "*FATAL ERROR*: Unknown FITS type in ",
537
                                "fitswrite()");
538
                        break;
539
    }
540
 
541
 
542
/* Now the tricky problem of (former) comments */
543
  flag=1;
544
  cstr = fitsbuf+10;
545
  for (i=71; --i; cstr++)
546
    {
547
    if (*cstr=='\'')
548
      flag ^= 1;
549
    else if (flag && *cstr=='/')
550
      break;
551
    }
552
  if (posoff==10 && i && (l=69-strlen(str))>0)
553
    {
554
    strncpy(str2, cstr, i);
555 22 bertin
    str2[i] = 0;
556 2 bertin
    strcat(str, " ");
557
    strncat(str, str2, l);
558
    }
559
 
560
  memset(fitsbuf+9, ' ', 71);
561
  fitsbuf += posoff;
562
 
563
/* Finally copy the result to the right place (except the trailing zero) */
564
  for (cstr = str; *cstr; *(fitsbuf++) = *(cstr++));
565
 
566
  return RETURN_OK;
567
  }
568
 
569
 
570
/****** fixexponent ***********************************************************
571
PROTO   void fixexponent(char *s)
572
PURPOSE Replaces the FORTRAN 'D' exponent sign to 'E' in a FITS line.
573
INPUT   FITS line
574
OUTPUT  -.
575
NOTES   -.
576
AUTHOR  E. Bertin (IAP & Leiden observatory)
577
VERSION 25/04/97
578
 ***/
579
void    fixexponent(char *s)
580
 
581
  {
582
   int  i;
583
 
584
  s += 9;
585 22 bertin
  for (i=71; ((int)*s) && (int)*s != '/' && i--; s++)
586 2 bertin
    if ((int)*s == 'D' || (int)*s == 'd')
587
      *s = (char)'E';
588
 
589
  return;
590
  }
591
 
592