| 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 |
|
|
|