LevelS C++ support library  3.83
fitshandle.cc
1 /*
2  * This file is part of libcxxsupport.
3  *
4  * libcxxsupport is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * libcxxsupport is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with libcxxsupport; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /*
20  * libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
21  * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
22  * (DLR).
23  */
24 
25 /*
26  * This file contains the implementation of the FITS I/O helper class
27  * used by the Planck LevelS package.
28  *
29  * Copyright (C) 2002-2011 Max-Planck-Society
30  * Author: Martin Reinecke
31  */
32 
33 #include <sstream>
34 #include <cstring>
35 #include <vector>
36 #include "fitsio.h"
37 #include "fitshandle.h"
38 #include "string_utils.h"
39 
40 #define FPTR (static_cast<fitsfile *> (fptr))
41 #define OFPTR (static_cast<fitsfile *> (orig.fptr))
42 
43 using namespace std;
44 
45 namespace {
46 
47 template<typename T> inline int fitsType();
48 template<> inline int fitsType<float> () { return TFLOAT; }
49 template<> inline int fitsType<double>() { return TDOUBLE; }
50 
51 int type2bitpix (PDT type)
52  {
53  switch (type)
54  {
55  case PLANCK_FLOAT32: return FLOAT_IMG;
56  case PLANCK_FLOAT64: return DOUBLE_IMG;
57  default: planck_fail ("unsupported component type");
58  }
59  }
60 
61 /*! Converts a FITS type code (i.e. the data type of a FITS column) to the
62  corresponding Planck type code. */
63 PDT ftc2type (int ftc)
64  {
65  switch (ftc)
66  {
67  case TLOGICAL : return PLANCK_BOOL;
68  case TBYTE : return PLANCK_INT8;
69  case TSHORT : return PLANCK_INT16;
70  case TINT :
71  case TINT32BIT: return PLANCK_INT32;
72  case TLONGLONG: return PLANCK_INT64;
73  case TFLOAT : return PLANCK_FLOAT32;
74  case TDOUBLE : return PLANCK_FLOAT64;
75  case TSTRING : return PLANCK_STRING;
76  default: planck_fail ("unsupported component type");
77  }
78  }
79 
80 /*! Converts a Planck type code to the corresponding FITS type code
81  (i.e. the data type of a FITS column). */
82 int type2ftc (PDT type)
83  {
84  switch (type)
85  {
86  case PLANCK_BOOL : return TLOGICAL;
87  case PLANCK_INT8 :
88  case PLANCK_UINT8 : return TBYTE;
89  case PLANCK_INT16 : return TSHORT;
90  case PLANCK_INT32 : return TINT;
91  case PLANCK_INT64 : return TLONGLONG;
92  case PLANCK_FLOAT32: return TFLOAT;
93  case PLANCK_FLOAT64: return TDOUBLE;
94  case PLANCK_STRING : return TSTRING;
95  default: planck_fail ("unsupported component type");
96  }
97  }
98 
99 const char *type2fitschar (PDT type)
100  {
101  switch (type)
102  {
103  case PLANCK_BOOL : return "L";
104  case PLANCK_FLOAT32: return "E";
105  case PLANCK_FLOAT64: return "D";
106  case PLANCK_INT8 :
107  case PLANCK_UINT8 : return "B";
108  case PLANCK_INT16 : return "I";
109  case PLANCK_INT32 : return "J";
110  case PLANCK_INT64 : return "K";
111  case PLANCK_STRING : return "A";
112  default:
113  planck_fail(string("unknown data type ")+type2string(type));
114  }
115  }
116 
117 const char *type2asciiform (PDT type)
118  {
119  switch (type)
120  {
121  case PLANCK_FLOAT32: return "E14.7";
122  case PLANCK_FLOAT64: return "D23.15";
123  case PLANCK_UINT8 : return "I3";
124  case PLANCK_INT8 : return "I4";
125  case PLANCK_INT16 : return "I6";
126  case PLANCK_INT32 : return "I11";
127  case PLANCK_INT64 : return "I22";
128  default:
129  planck_fail(string("unknown data type ")+type2string(type));
130  }
131  }
132 
133 string fixkey (const string &key)
134  {
135  for (tsize m=0; m<key.size(); ++m)
136  if (islower(key[m])) return string("HIERARCH "+key);
137 
138  return key;
139  }
140 } // unnamed namespace
141 
142 fitscolumn::fitscolumn()
143  : repcount_(0), type_(PLANCK_INVALID) {}
144 
145 fitscolumn::fitscolumn (const string &nm, const string &un, int64 rc, PDT tp)
146  : name_(nm), unit_(un), repcount_(rc), type_(tp) {}
147 
148 fitscolumn::~fitscolumn () {}
149 
150 void fitshandle::check_errors() const
151  {
152  char msg[81];
153  if (status==0)
154  {
155  while (fits_read_errmsg(msg))
156  cerr << "STALE FITS ERROR MESSAGE: " << msg << endl;
157  fits_clear_errmsg();
158  return;
159  }
160  fits_get_errstatus (status, msg);
161  cerr << msg << endl;
162  while (fits_read_errmsg(msg)) cerr << msg << endl;
163  fits_clear_errmsg();
164  status=0;
165  planck_fail("FITS error");
166  }
167 
168 void fitshandle::clean_data()
169  {
170  if (!fptr) return;
171  axes_.clear();
172  columns_.clear();
173  hdutype_=INVALID;
174  bitpix_=INVALID;
175  nrows_=0;
176  }
177 
178 void fitshandle::clean_all()
179  {
180  if (!fptr) return;
181  clean_data();
182  fits_close_file (FPTR, &status);
183  check_errors();
184  fptr=0;
185  }
186 
187 bool fitshandle::table_hdu (tsize col) const
188  {
189  if ((hdutype_!=ASCII_TBL) && (hdutype_!=BINARY_TBL)) return false;
190  if ((col<=0) || (col>columns_.size())) return false;
191  return true;
192  }
193 bool fitshandle::image_hdu () const
194  { return hdutype_==IMAGE_HDU; }
195 
196 void fitshandle::init_image()
197  {
198  int naxis;
199  fits_get_img_type (FPTR, &bitpix_, &status);
200  fits_get_img_dim (FPTR, &naxis, &status);
201  check_errors();
202  arr<LONGLONG> naxes(naxis);
203  if (naxis>0) fits_get_img_sizell (FPTR, naxis, naxes.begin(), &status);
204  for (long m=0; m<naxis; ++m) axes_.push_back(naxes[naxis-m-1]);
205  check_errors();
206  }
207 
208 void fitshandle::init_asciitab()
209  {
210  char ttype[81], tunit[81], tform[81];
211  int ncol, typecode;
212  fits_get_num_cols (FPTR, &ncol, &status);
213  { LONGLONG tmp; fits_get_num_rowsll (FPTR, &tmp, &status); nrows_=tmp; }
214  check_errors();
215  for (int m=1; m<=ncol; ++m)
216  {
217  fits_get_acolparms (FPTR, m, ttype, 0, tunit, tform,
218  0, 0, 0, 0, &status);
219  fits_ascii_tform (tform, &typecode, 0,0, &status);
220  check_errors();
221  columns_.push_back (fitscolumn (ttype,tunit,1,ftc2type(typecode)));
222  }
223  }
224 
225 void fitshandle::init_bintab()
226  {
227  char ttype[81], tunit[81], tform[81];
228  LONGLONG repc;
229  int ncol, typecode;
230  fits_get_num_cols (FPTR, &ncol, &status);
231  { LONGLONG tmp; fits_get_num_rowsll (FPTR, &tmp, &status); nrows_=tmp; }
232  check_errors();
233  for (int m=1; m<=ncol; ++m)
234  {
235  fits_get_bcolparmsll (FPTR, m, ttype, tunit, tform, &repc,
236  0, 0, 0, 0, &status);
237  fits_binary_tform (tform, &typecode, 0,0, &status);
238  check_errors();
239  columns_.push_back (fitscolumn (ttype,tunit,repc,ftc2type(typecode)));
240  }
241  }
242 
243 void fitshandle::init_data()
244  {
245  clean_data();
246  fits_get_hdu_type (FPTR, &hdutype_, &status);
247  check_errors();
248  switch(hdutype_)
249  {
250  case IMAGE_HDU:
251  init_image(); break;
252  case ASCII_TBL:
253  init_asciitab(); break;
254  case BINARY_TBL:
255  init_bintab(); break;
256  default:
257  planck_fail("init_data(): unsupported HDU type"); break;
258  }
259  }
260 
261 void fitshandle::read_col (int colnum, void *data, int64 ndata, PDT type,
262  int64 offset) const
263  {
264  planck_assert(table_hdu(colnum),"incorrect FITS table access");
265  int64 repc = columns_[colnum-1].repcount();
266  planck_assert (ndata<=(repc*nrows_-offset),"read_column(): array too large");
267  int64 frow = offset/repc+1;
268  int64 felem = offset%repc+1;
269  fits_read_col (FPTR, type2ftc(type), colnum, frow, felem, ndata, 0, data, 0,
270  &status);
271  check_errors();
272  }
273 void fitshandle::write_col (int colnum, const void *data, int64 ndata,
274  PDT type, int64 offset)
275  {
276  planck_assert(table_hdu(colnum),"incorrect FITS table access");
277  int64 repc = columns_[colnum-1].repcount();
278  int64 frow = offset/repc+1;
279  int64 felem = offset%repc+1;
280  fits_write_col (FPTR, type2ftc(type), colnum, frow, felem, ndata,
281  const_cast<void *>(data), &status);
282  nrows_ = max(nrows_,offset+ndata);
283  check_errors();
284  }
285 
286 void fitshandle::getKeyHelper(const string &name) const
287  {
288  if (status==KEY_NO_EXIST)
289  {
290  fits_clear_errmsg();
291  status=0;
292  planck_fail("fitshandle::get_key(): key '"+name+"' not found");
293  }
294  check_errors();
295  }
296 
298  : status(0), fptr(0), hdutype_(INVALID), bitpix_(INVALID), nrows_(0) {}
299 
301  { clean_all(); }
302 
303 void fitshandle::open (const string &fname)
304  {
305  clean_all();
306  fitsfile *ptr;
307  fits_open_file(&ptr, fname.c_str(), READONLY, &status);
308  fptr=ptr;
309  check_errors();
310  init_data();
311  }
312 
313 void fitshandle::create (const string &fname)
314  {
315  clean_all();
316  fitsfile *ptr;
317  fits_create_file(&ptr, fname.c_str(), &status);
318  fptr=ptr;
319  fits_write_imghdr(FPTR, 8, 0, 0, &status); // insert empty PHDU
320  fits_write_date(FPTR, &status);
321  check_errors();
322  init_data();
323  }
324 
325 // static
326 void fitshandle::delete_file (const string &name)
327  {
328  fitsfile *ptr;
329  int stat = 0;
330  fits_open_file(&ptr, name.c_str(), READWRITE, &stat);
331  fits_delete_file(ptr, &stat);
332  if (stat==0) return;
333 
334  char msg[81];
335  fits_get_errstatus (stat, msg);
336  cerr << msg << endl;
337  while (fits_read_errmsg(msg)) cerr << msg << endl;
338  planck_fail("FITS error");
339  }
340 
341 string fitshandle::fileName() const
342  {
343  planck_assert(connected(),"handle not connected to a file");
344  char *fname = new char[2048];
345  fits_file_name(FPTR, fname, &status);
346  check_errors();
347  string result(fname);
348  delete[] fname;
349  return result;
350  }
351 
352 void fitshandle::goto_hdu (int hdu)
353  {
354  int curhdu;
355  fits_get_hdu_num(FPTR,&curhdu);
356  if (curhdu!=hdu)
357  {
358  fits_movabs_hdu(FPTR, hdu, &hdutype_, &status);
359  check_errors();
360  init_data();
361  }
362  }
363 
365  {
366  int result;
367  fits_get_num_hdus (FPTR, &result, &status);
368  check_errors();
369  return result;
370  }
371 
372 void fitshandle::insert_bintab (const vector<fitscolumn> &cols,
373  const string &extname)
374  {
375  clean_data();
376  int ncol=cols.size();
377  arr2b<char> ttype(ncol,81), tform(ncol,81), tunit(ncol,81);
378 
379  for (long m=0; m<ncol; ++m)
380  {
381  strcpy (ttype[m], cols[m].name().c_str());
382  strcpy (tunit[m], cols[m].unit().c_str());
383  ostringstream x;
384  x << cols[m].repcount() << type2fitschar(cols[m].type());
385  strcpy (tform[m], x.str().c_str());
386  }
387  fits_insert_btbl (FPTR, nrows_, ncol, ttype.p0(), tform.p0(), tunit.p0(),
388  const_cast<char *>(extname.c_str()), 0, &status);
389  check_errors();
390  init_data();
391  }
392 
393 void fitshandle::insert_asctab (const vector<fitscolumn> &cols,
394  const string &extname)
395  {
396  clean_data();
397  int ncol=cols.size();
398  arr2b<char> ttype(ncol,81), tform(ncol,81), tunit(ncol,81);
399 
400  for (long m=0; m<ncol; ++m)
401  {
402  strcpy (ttype[m], cols[m].name().c_str());
403  strcpy (tunit[m], cols[m].unit().c_str());
404  ostringstream x;
405  if (cols[m].type()!=PLANCK_STRING)
406  {
407  planck_assert (cols[m].repcount()==1,"bad repcount for ASCII table");
408  x << type2asciiform(cols[m].type());
409  }
410  else
411  {
412  x << "A" << dataToString(cols[m].repcount());
413  }
414  strcpy (tform[m], x.str().c_str());
415  }
416  fits_insert_atbl (FPTR, 0, nrows_, ncol, ttype.p0(), 0, tform.p0(),
417  tunit.p0(), const_cast<char *>(extname.c_str()), &status);
418  check_errors();
419  init_data();
420  }
421 
422 void fitshandle::insert_image (PDT type, const vector<int64> &Axes)
423  {
424  clean_data();
425  arr<LONGLONG> tmpax(Axes.size());
426  for (long m=0; m<long(Axes.size()); m++) tmpax[m]=Axes[Axes.size()-1-m];
427  fits_insert_imgll (FPTR, type2bitpix(type), Axes.size(), &tmpax[0], &status);
428  check_errors();
429  init_data();
430  }
431 
432 template<typename T>
433  void fitshandle::insert_image (PDT type, const arr2<T> &data)
434  {
435  clean_data();
436  arr<LONGLONG> tmpax(2);
437  tmpax[0] = data.size2(); tmpax[1] = data.size1();
438  fits_insert_imgll (FPTR, type2bitpix(type), 2, &tmpax[0], &status);
439  arr2<T> &tmparr = const_cast<arr2<T> &> (data);
440  fits_write_img (FPTR, fitsType<T>(), 1, tmpax[0]*tmpax[1],
441  &tmparr[0][0], &status);
442  check_errors();
443  init_data();
444  }
445 
446 template void fitshandle::insert_image (PDT type, const arr2<double> &data);
447 template void fitshandle::insert_image (PDT type, const arr2<float> &data);
448 
450  {
451  planck_assert(connected(),"handle not connected to a file");
452  fits_write_chksum (FPTR, &status);
453  check_errors();
454  }
455 
456 const vector<int64> &fitshandle::axes() const
457  {
458  planck_assert(image_hdu(),"not connected to an image");
459  return axes_;
460  }
461 const string &fitshandle::colname(int i) const
462  {
463  planck_assert(table_hdu(i),"incorrect FITS table access");
464  return columns_[i-1].name();
465  }
466 const string &fitshandle::colunit(int i) const
467  {
468  planck_assert(table_hdu(i),"incorrect FITS table access");
469  return columns_[i-1].unit();
470  }
471 int64 fitshandle::repcount(int i) const
472  {
473  planck_assert(table_hdu(i),"incorrect FITS table access");
474  return columns_[i-1].repcount();
475  }
477  {
478  planck_assert(table_hdu(i),"incorrect FITS table access");
479  return columns_[i-1].type();
480  }
481 int fitshandle::ncols() const
482  {
483  planck_assert(table_hdu(1),"incorrect FITS table access");
484  return columns_.size();
485  }
486 int64 fitshandle::nrows() const
487  {
488  planck_assert(table_hdu(1),"incorrect FITS table access");
489  return nrows_;
490  }
491 int64 fitshandle::nelems(int i) const
492  {
493  planck_assert(table_hdu(i),"incorrect FITS table access");
494  if (columns_[i-1].type()==PLANCK_STRING) return nrows_;
495  return nrows_*columns_[i-1].repcount();
496  }
498  {
499  planck_assert(table_hdu(1),"incorrect FITS table access");
500  long int res;
501  fits_get_rowsize(FPTR, &res, &status);
502  planck_assert(res>=1,"bad recommended FITS chunk size");
503  check_errors();
504  return res*columns_[i-1].repcount();
505  }
506 
507 void fitshandle::get_all_keys(vector<string> &keys) const
508  {
509  keys.clear();
510  char card[81];
511  const char *inclist[] = { "*" };
512  planck_assert(connected(),"handle not connected to a file");
513  fits_read_record (FPTR, 0, card, &status);
514  check_errors();
515  while (true)
516  {
517  fits_find_nextkey (FPTR, const_cast<char **>(inclist), 1,
518  0, 0, card, &status);
519  if (status!=0) break;
520  if (fits_get_keyclass(card)==TYP_USER_KEY)
521  {
522  char keyname[80];
523  int dummy;
524  fits_get_keyname(card, keyname, &dummy, &status);
525  check_errors();
526  keys.push_back(trim(keyname));
527  }
528  check_errors();
529  }
530  if (status==KEY_NO_EXIST) { fits_clear_errmsg(); status=0; }
531  check_errors();
532  }
533 
534 void fitshandle::set_key_void (const string &key, const void *value,
535  PDT type, const string &comment)
536  {
537  planck_assert(connected(),"handle not connected to a file");
538  string key2 = fixkey(key);
539  switch (type)
540  {
541  case PLANCK_INT8:
542  case PLANCK_UINT8:
543  case PLANCK_INT16:
544  case PLANCK_INT32:
545  case PLANCK_INT64:
546  case PLANCK_FLOAT32:
547  case PLANCK_FLOAT64:
548  fits_update_key (FPTR, type2ftc(type), const_cast<char *>(key2.c_str()),
549  const_cast<void *>(value), const_cast<char *>(comment.c_str()),
550  &status);
551  break;
552  case PLANCK_BOOL:
553  {
554  int val = *(static_cast<const bool *>(value));
555  fits_update_key (FPTR, TLOGICAL, const_cast<char *>(key2.c_str()),
556  &val, const_cast<char *>(comment.c_str()), &status);
557  break;
558  }
559  case PLANCK_STRING:
560  {
561  string val = *(static_cast<const string *>(value));
562  fits_update_key_longstr (FPTR, const_cast<char *>(key2.c_str()),
563  const_cast<char *>(val.c_str()), const_cast<char *>(comment.c_str()),
564  &status);
565  break;
566  }
567  default:
568  planck_fail ("unsupported data type in set_key_void()");
569  }
570  check_errors();
571  }
572 
573 void fitshandle::get_key_void (const string &name, void *value, PDT type) const
574  {
575  planck_assert(connected(),"handle not connected to a file");
576  switch (type)
577  {
578  case PLANCK_INT8:
579  case PLANCK_UINT8:
580  case PLANCK_INT16:
581  case PLANCK_INT32:
582  case PLANCK_INT64:
583  case PLANCK_FLOAT32:
584  case PLANCK_FLOAT64:
585  fits_read_key (FPTR, type2ftc(type), const_cast<char *>(name.c_str()),
586  value, 0, &status);
587  getKeyHelper(name);
588  break;
589  case PLANCK_BOOL:
590  {
591  int val;
592  fits_read_key (FPTR, TLOGICAL, const_cast<char *>(name.c_str()), &val, 0,
593  &status);
594  getKeyHelper(name);
595  *(static_cast<bool *>(value))=val;
596  break;
597  }
598  case PLANCK_STRING:
599  {
600  char *tmp=0;
601  fits_read_key_longstr (FPTR, const_cast<char *>(name.c_str()), &tmp, 0,
602  &status);
603  getKeyHelper(name);
604  *(static_cast<string *>(value))=tmp;
605  if (tmp) free(tmp);
606  break;
607  }
608  default:
609  planck_fail ("unsupported data type in get_key_void()");
610  }
611  check_errors();
612  }
613 
614 void fitshandle::delete_key (const string &name)
615  {
616  planck_assert(connected(),"handle not connected to a file");
617  fits_delete_key (FPTR, const_cast<char *>(name.c_str()), &status);
618  check_errors();
619  }
620 
621 void fitshandle::add_comment(const string &comment)
622  {
623  planck_assert(connected(),"handle not connected to a file");
624  fits_write_comment(FPTR,const_cast<char *>(comment.c_str()),&status);
625  check_errors();
626  }
627 
628 bool fitshandle::key_present(const string &name) const
629  {
630  char card[81];
631  planck_assert(connected(),"handle not connected to a file");
632  fits_read_card(FPTR, const_cast<char *>(name.c_str()), card, &status);
633  if (status==KEY_NO_EXIST)
634  { fits_clear_errmsg(); status=0; return false; }
635  check_errors();
636  return true;
637  }
638 
639 void fitshandle::assert_pdmtype (const string &pdmtype) const
640  {
641  string type;
642  get_key("PDMTYPE",type);
643  if (pdmtype==type) return;
644  cerr << "PDMTYPE " << pdmtype << " expected, but found " << type << endl;
645  }
646 
647 void fitshandle::read_column_raw_void
648  (int colnum, void *data, PDT type, int64 num, int64 offset) const
649  {
650  switch (type)
651  {
652  case PLANCK_INT8:
653  case PLANCK_UINT8:
654  case PLANCK_INT16:
655  case PLANCK_INT32:
656  case PLANCK_INT64:
657  case PLANCK_FLOAT32:
658  case PLANCK_FLOAT64:
659  case PLANCK_BOOL:
660  read_col (colnum, data, num, type, offset); break;
661  case PLANCK_STRING:
662  {
663  string *data2 = static_cast<string *> (data);
664  planck_assert(table_hdu(colnum),"incorrect FITS table access");
665  planck_assert (num<=(nrows_-offset),
666  "read_column(): array too large");
667  arr2b<char> tdata(safe_cast<tsize>(num),
668  safe_cast<tsize>(columns_[colnum-1].repcount()+1));
669  int dispwidth;
670  fits_get_col_display_width(FPTR, colnum, &dispwidth, &status);
671  planck_assert(dispwidth<=columns_[colnum-1].repcount(),"column too wide");
672  fits_read_col (FPTR, TSTRING, colnum, offset+1, 1, num,
673  0, tdata.p0(), 0, &status);
674  check_errors();
675  for (long m=0;m<num;++m) data2[m]=tdata[m];
676  break;
677  }
678  default:
679  planck_fail ("unsupported data type in read_column_raw_void()");
680  }
681  }
682 
683 void fitshandle::write_column_raw_void
684  (int colnum, const void *data, PDT type, int64 num, int64 offset)
685  {
686  switch (type)
687  {
688  case PLANCK_INT8:
689  case PLANCK_UINT8:
690  case PLANCK_INT16:
691  case PLANCK_INT32:
692  case PLANCK_INT64:
693  case PLANCK_FLOAT32:
694  case PLANCK_FLOAT64:
695  case PLANCK_BOOL:
696  write_col (colnum, data, num, type, offset); break;
697  case PLANCK_STRING:
698  {
699  const string *data2 = static_cast<const string *> (data);
700  planck_assert(table_hdu(colnum),"incorrect FITS table access");
701  tsize stringlen = safe_cast<tsize>(columns_[colnum-1].repcount()+1);
702  arr2b<char> tdata(safe_cast<tsize>(num), stringlen);
703  for (long m=0;m<num;++m)
704  {
705  strncpy(tdata[m],data2[m].c_str(),stringlen-1);
706  tdata[m][stringlen-1] = '\0';
707  }
708  fits_write_col (FPTR, TSTRING, colnum, offset+1, 1, num,
709  tdata.p0(), &status);
710  nrows_ = max(nrows_,offset+num);
711  check_errors();
712  break;
713  }
714  default:
715  planck_fail ("unsupported data type in write_column_raw_void()");
716  }
717  }
718 
719 void fitshandle::write_image2D_void (const void *data, PDT type, tsize s1,
720  tsize s2)
721  {
722  planck_assert(image_hdu(),"not connected to an image");
723  planck_assert (axes_.size()==2, "wrong number of dimensions");
724  planck_assert (axes_[0]==int64(s1), "wrong size of dimension 1");
725  planck_assert (axes_[1]==int64(s2), "wrong size of dimension 2");
726 
727  fits_write_img (FPTR, type2ftc(type), 1, axes_[0]*axes_[1],
728  const_cast<void *>(data), &status);
729  check_errors();
730  }
731 
732 void fitshandle::write_subimage_void (const void *data, PDT type, tsize sz,
733  int64 offset)
734  {
735  planck_assert(image_hdu(),"not connected to an image");
736  fits_write_img (FPTR, type2ftc(type), 1+offset, sz, const_cast<void *>(data),
737  &status);
738  check_errors();
739  }
740 
741 template<typename T> void fitshandle::read_image (arr2<T> &data) const
742  {
743  planck_assert(image_hdu(),"not connected to an image");
744  planck_assert (axes_.size()==2, "wrong number of dimensions");
745  data.alloc(safe_cast<tsize>(axes_[0]), safe_cast<tsize>(axes_[1]));
746  fits_read_img (FPTR, fitsType<T>(), 1, axes_[0]*axes_[1], 0, &data[0][0], 0,
747  &status);
748  check_errors();
749  }
750 
751 template void fitshandle::read_image (arr2<float> &data) const;
752 template void fitshandle::read_image (arr2<double> &data) const;
753 
754 template<typename T> void fitshandle::read_image (arr3<T> &data) const
755  {
756  planck_assert(image_hdu(),"not connected to an image");
757  planck_assert (axes_.size()==3, "wrong number of dimensions");
758  data.alloc(safe_cast<tsize>(axes_[0]), safe_cast<tsize>(axes_[1]),
759  safe_cast<tsize>(axes_[2]));
760  fits_read_img (FPTR, fitsType<T>(), 1, axes_[0]*axes_[1]*axes_[2],
761  0, &data(0,0,0), 0, &status);
762  check_errors();
763  }
764 
765 template void fitshandle::read_image (arr3<float> &data) const;
766 template void fitshandle::read_image (arr3<double> &data) const;
767 
768 template<typename T> void fitshandle::read_subimage
769  (arr2<T> &data, int xl, int yl) const
770  {
771  planck_assert(image_hdu(),"not connected to an image");
772  planck_assert (axes_.size()==2, "wrong number of dimensions");
773  for (tsize m=0; m<data.size1(); ++m)
774  fits_read_img (FPTR, fitsType<T>(), (xl+m)*axes_[1]+yl+1,
775  data.size2(), 0, &data[m][0], 0, &status);
776  check_errors();
777  }
778 
779 template void fitshandle::read_subimage
780  (arr2<float> &data, int xl, int yl) const;
781 template void fitshandle::read_subimage
782  (arr2<double> &data, int xl, int yl) const;
783 
784 void fitshandle::read_subimage_void (void *data, PDT type, tsize ndata,
785  int64 offset) const
786  {
787  planck_assert(image_hdu(),"not connected to an image");
788  fits_read_img (FPTR, type2ftc(type), 1+offset, ndata, 0, data, 0, &status);
789  check_errors();
790  }
791 
792 namespace {
793 
794 class cfitsio_checker
795  {
796  public:
797  cfitsio_checker()
798  {
799  float fitsversion;
800  planck_assert(fits_get_version(&fitsversion),
801  "error calling fits_get_version()");
802  /* CFITSIO 4.x switched to a three version format (4.0.0), as opposed
803  * to previous two-number versions (3.47). Version 4 defines a new macro
804  * CFITSIO_MICRO to track the patch level in the version. We check if
805  * macro is defined, and fall back to the old behaviour if it is not.
806  * If it is, we adapt to the new value returned by 'fits_get_version'.
807  */
808 #ifdef CFITSIO_MICRO
809  int v_header = nearest<int>(10000*CFITSIO_MAJOR + 100*CFITSIO_MINOR + CFITSIO_MICRO),
810  v_library = nearest<int>(10000*fitsversion);
811  if (v_header!=v_library)
812  cerr << endl << "WARNING: version mismatch between CFITSIO header (v"
813  << dataToString(v_header) << ") and linked library (v"
814  << dataToString(v_library) << ")." << endl << endl;
815 #else
816  int v_header = nearest<int>(100*CFITSIO_VERSION),
817  v_library = nearest<int>(100*fitsversion);
818  if (v_header!=v_library)
819  cerr << endl << "WARNING: version mismatch between CFITSIO header (v"
820  << dataToString(v_header*0.01) << ") and linked library (v"
821  << dataToString(v_library*0.01) << ")." << endl << endl;
822 #endif
823  }
824  };
825 
826 cfitsio_checker Cfitsio_Checker;
827 
828 } // unnamed namespace
void create(const std::string &fname)
Definition: fitshandle.cc:313
T1 safe_cast(const T2 &arg)
Definition: safe_cast.h:86
int64 nelems(int i) const
Definition: fitshandle.cc:491
void get_key(const std::string &name, T &value) const
Definition: fitshandle.h:201
int num_hdus() const
Definition: fitshandle.cc:364
void assert_pdmtype(const std::string &pdmtype) const
Definition: fitshandle.cc:639
void write_checksum()
Definition: fitshandle.cc:449
int64 repcount(int i) const
Definition: fitshandle.cc:471
void open(const std::string &fname)
Definition: fitshandle.cc:303
void goto_hdu(int hdu)
Definition: fitshandle.cc:352
int64 efficientChunkSize(int i) const
Definition: fitshandle.cc:497
Definition: arr.h:474
Definition: arr.h:511
void alloc(tsize sz1, tsize sz2, tsize sz3)
Definition: arr.h:610
void insert_asctab(const std::vector< fitscolumn > &cols, const std::string &extname="xtension")
Definition: fitshandle.cc:393
int64 nrows() const
Definition: fitshandle.cc:486
void insert_bintab(const std::vector< fitscolumn > &cols, const std::string &extname="xtension")
Definition: fitshandle.cc:372
const std::string & colname(int i) const
Definition: fitshandle.cc:461
void get_all_keys(std::vector< std::string > &keys) const
Definition: fitshandle.cc:507
void delete_key(const std::string &name)
Definition: fitshandle.cc:614
T ** p0()
Definition: arr.h:574
tsize size1() const
Definition: arr.h:375
Definition: arr.h:581
int ncols() const
Definition: fitshandle.cc:481
std::size_t tsize
Definition: datatypes.h:116
std::string fileName() const
Definition: fitshandle.cc:341
PDT coltype(int i) const
Definition: fitshandle.cc:476
PDT
Definition: datatypes.h:121
std::string trim(const std::string &orig)
Definition: arr.h:300
void read_image(arr2< T > &data) const
Definition: fitshandle.cc:741
void read_subimage(arr2< T > &data, int xl, int yl) const
Definition: fitshandle.cc:769
string dataToString(const T &x)
Definition: string_utils.cc:52
#define planck_assert(testval, msg)
#define planck_fail(msg)
void add_comment(const std::string &comment)
Definition: fitshandle.cc:621
void alloc(tsize sz1, tsize sz2)
Definition: arr.h:385
bool key_present(const std::string &name) const
Definition: fitshandle.cc:628
const std::vector< int64 > & axes() const
Definition: fitshandle.cc:456
void insert_image(PDT type, const std::vector< int64 > &Axes)
tsize size2() const
Definition: arr.h:377
static void delete_file(const std::string &name)
Definition: fitshandle.cc:326
const char * type2string(PDT type)
Definition: datatypes.h:193
const std::string & colunit(int i) const
Definition: fitshandle.cc:466

Generated on Wed Nov 13 2024 12:18:16 for LevelS C++ support library