fitshandle.cc

00001 /*
00002  *  This file is part of libcxxsupport.
00003  *
00004  *  libcxxsupport is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  libcxxsupport is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with libcxxsupport; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  */
00018 
00019 /*
00020  *  libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
00021  *  and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
00022  *  (DLR).
00023  */
00024 
00025 /*
00026  *  This file contains the implementation of the FITS I/O helper class
00027  *  used by the Planck LevelS package.
00028  *
00029  *  Copyright (C) 2002-2011 Max-Planck-Society
00030  *  Author: Martin Reinecke
00031  */
00032 
00033 #include <sstream>
00034 #include <cstring>
00035 #include <vector>
00036 #include "fitsio.h"
00037 #include "fitshandle.h"
00038 #include "string_utils.h"
00039 
00040 #define FPTR (static_cast<fitsfile *> (fptr))
00041 #define OFPTR (static_cast<fitsfile *> (orig.fptr))
00042 
00043 using namespace std;
00044 
00045 namespace {
00046 
00047 template<typename T> inline int fitsType();
00048 template<> inline int fitsType<float> () { return TFLOAT;  }
00049 template<> inline int fitsType<double>() { return TDOUBLE; }
00050 
00051 int type2bitpix (PDT type)
00052   {
00053   switch (type)
00054     {
00055     case PLANCK_FLOAT32: return FLOAT_IMG;
00056     case PLANCK_FLOAT64: return DOUBLE_IMG;
00057     default: planck_fail ("unsupported component type");
00058     }
00059   }
00060 
00061 /*! Converts a FITS type code (i.e. the data type of a FITS column) to the
00062     corresponding Planck type code. */
00063 PDT ftc2type (int ftc)
00064   {
00065   switch (ftc)
00066     {
00067     case TLOGICAL : return PLANCK_BOOL;
00068     case TBYTE    : return PLANCK_INT8;
00069     case TSHORT   : return PLANCK_INT16;
00070     case TINT     :
00071     case TINT32BIT: return PLANCK_INT32;
00072     case TLONGLONG: return PLANCK_INT64;
00073     case TFLOAT   : return PLANCK_FLOAT32;
00074     case TDOUBLE  : return PLANCK_FLOAT64;
00075     case TSTRING  : return PLANCK_STRING;
00076     default: planck_fail ("unsupported component type");
00077     }
00078   }
00079 
00080 /*! Converts a Planck type code to the corresponding FITS type code
00081     (i.e. the data type of a FITS column). */
00082 int type2ftc (PDT type)
00083   {
00084   switch (type)
00085     {
00086     case PLANCK_BOOL   : return TLOGICAL;
00087     case PLANCK_INT8   :
00088     case PLANCK_UINT8  : return TBYTE;
00089     case PLANCK_INT16  : return TSHORT;
00090     case PLANCK_INT32  : return TINT;
00091     case PLANCK_INT64  : return TLONGLONG;
00092     case PLANCK_FLOAT32: return TFLOAT;
00093     case PLANCK_FLOAT64: return TDOUBLE;
00094     case PLANCK_STRING : return TSTRING;
00095     default: planck_fail ("unsupported component type");
00096     }
00097   }
00098 
00099 const char *type2fitschar (PDT type)
00100   {
00101   switch (type)
00102     {
00103     case PLANCK_BOOL   : return "L";
00104     case PLANCK_FLOAT32: return "E";
00105     case PLANCK_FLOAT64: return "D";
00106     case PLANCK_INT8   :
00107     case PLANCK_UINT8  : return "B";
00108     case PLANCK_INT16  : return "I";
00109     case PLANCK_INT32  : return "J";
00110     case PLANCK_INT64  : return "K";
00111     case PLANCK_STRING : return "A";
00112     default:
00113       planck_fail(string("unknown data type ")+type2string(type));
00114     }
00115   }
00116 
00117 const char *type2asciiform (PDT type)
00118   {
00119   switch (type)
00120     {
00121     case PLANCK_FLOAT32: return "E14.7";
00122     case PLANCK_FLOAT64: return "D23.15";
00123     case PLANCK_UINT8  : return "I3";
00124     case PLANCK_INT8   : return "I4";
00125     case PLANCK_INT16  : return "I6";
00126     case PLANCK_INT32  : return "I11";
00127     case PLANCK_INT64  : return "I22";
00128     default:
00129       planck_fail(string("unknown data type ")+type2string(type));
00130     }
00131   }
00132 
00133 string fixkey (const string &key)
00134   {
00135   for (tsize m=0; m<key.size(); ++m)
00136     if (islower(key[m])) return string("HIERARCH "+key);
00137 
00138   return key;
00139   }
00140 } // unnamed namespace
00141 
00142 fitscolumn::fitscolumn()
00143   : repcount_(0), type_(PLANCK_INVALID) {}
00144 
00145 fitscolumn::fitscolumn (const string &nm, const string &un, int64 rc, PDT tp)
00146   : name_(nm), unit_(un), repcount_(rc), type_(tp) {}
00147 
00148 fitscolumn::~fitscolumn () {}
00149 
00150 void fitshandle::check_errors() const
00151   {
00152   char msg[81];
00153   if (status==0)
00154     {
00155     while (fits_read_errmsg(msg))
00156       cerr << "STALE FITS ERROR MESSAGE: " << msg << endl;
00157     fits_clear_errmsg();
00158     return;
00159     }
00160   fits_get_errstatus (status, msg);
00161   cerr << msg << endl;
00162   while (fits_read_errmsg(msg)) cerr << msg << endl;
00163   fits_clear_errmsg();
00164   status=0;
00165   planck_fail("FITS error");
00166   }
00167 
00168 void fitshandle::clean_data()
00169   {
00170   if (!fptr) return;
00171   axes_.clear();
00172   columns_.clear();
00173   hdutype_=INVALID;
00174   bitpix_=INVALID;
00175   nrows_=0;
00176   }
00177 
00178 void fitshandle::clean_all()
00179   {
00180   if (!fptr) return;
00181   clean_data();
00182   fits_close_file (FPTR, &status);
00183   check_errors();
00184   fptr=0;
00185   }
00186 
00187 bool fitshandle::table_hdu (tsize col) const
00188   {
00189   if ((hdutype_!=ASCII_TBL) && (hdutype_!=BINARY_TBL)) return false;
00190   if ((col<=0) || (col>columns_.size())) return false;
00191   return true;
00192   }
00193 bool fitshandle::image_hdu () const
00194   { return hdutype_==IMAGE_HDU; }
00195 
00196 void fitshandle::init_image()
00197   {
00198   int naxis;
00199   fits_get_img_type (FPTR, &bitpix_, &status);
00200   fits_get_img_dim (FPTR, &naxis, &status);
00201   check_errors();
00202   arr<LONGLONG> naxes(naxis);
00203   fits_get_img_sizell (FPTR, naxis, &naxes[0], &status);
00204   for (long m=0; m<naxis; ++m) axes_.push_back(naxes[naxis-m-1]);
00205   check_errors();
00206   }
00207 
00208 void fitshandle::init_asciitab()
00209   {
00210   char ttype[81], tunit[81], tform[81];
00211   int ncol, typecode;
00212   fits_get_num_cols (FPTR, &ncol, &status);
00213   { LONGLONG tmp; fits_get_num_rowsll (FPTR, &tmp, &status); nrows_=tmp; }
00214   check_errors();
00215   for (int m=1; m<=ncol; ++m)
00216     {
00217     fits_get_acolparms (FPTR, m, ttype, 0, tunit, tform,
00218                         0, 0, 0, 0, &status);
00219     fits_ascii_tform (tform, &typecode, 0,0, &status);
00220     check_errors();
00221     columns_.push_back (fitscolumn (ttype,tunit,1,ftc2type(typecode)));
00222     }
00223   }
00224 
00225 void fitshandle::init_bintab()
00226   {
00227   char ttype[81], tunit[81], tform[81];
00228   LONGLONG repc;
00229   int ncol, typecode;
00230   fits_get_num_cols (FPTR, &ncol, &status);
00231   { LONGLONG tmp; fits_get_num_rowsll (FPTR, &tmp, &status); nrows_=tmp; }
00232   check_errors();
00233   for (int m=1; m<=ncol; ++m)
00234     {
00235     fits_get_bcolparmsll (FPTR, m, ttype, tunit, tform, &repc,
00236                         0, 0, 0, 0, &status);
00237     fits_binary_tform (tform, &typecode, 0,0, &status);
00238     check_errors();
00239     columns_.push_back (fitscolumn (ttype,tunit,repc,ftc2type(typecode)));
00240     }
00241   }
00242 
00243 void fitshandle::init_data()
00244   {
00245   clean_data();
00246   fits_get_hdu_type (FPTR, &hdutype_, &status);
00247   check_errors();
00248   switch(hdutype_)
00249     {
00250     case IMAGE_HDU:
00251       init_image(); break;
00252     case ASCII_TBL:
00253       init_asciitab(); break;
00254     case BINARY_TBL:
00255       init_bintab(); break;
00256     default:
00257       planck_fail("init_data(): unsupported HDU type"); break;
00258     }
00259   }
00260 
00261 void fitshandle::read_col (int colnum, void *data, int64 ndata, PDT type,
00262   int64 offset) const
00263   {
00264   planck_assert(table_hdu(colnum),"incorrect FITS table access");
00265   int64 repc = columns_[colnum-1].repcount();
00266   planck_assert (ndata<=(repc*nrows_-offset),"read_column(): array too large");
00267   int64 frow = offset/repc+1;
00268   int64 felem = offset%repc+1;
00269   fits_read_col (FPTR, type2ftc(type), colnum, frow, felem, ndata, 0, data, 0,
00270     &status);
00271   check_errors();
00272   }
00273 void fitshandle::write_col (int colnum, const void *data, int64 ndata,
00274   PDT type, int64 offset)
00275   {
00276   planck_assert(table_hdu(colnum),"incorrect FITS table access");
00277   int64 repc = columns_[colnum-1].repcount();
00278   int64 frow = offset/repc+1;
00279   int64 felem = offset%repc+1;
00280   fits_write_col (FPTR, type2ftc(type), colnum, frow, felem, ndata,
00281     const_cast<void *>(data), &status);
00282   nrows_ = max(nrows_,offset+ndata);
00283   check_errors();
00284   }
00285 
00286 void fitshandle::getKeyHelper(const string &name) const
00287   {
00288   if (status==KEY_NO_EXIST)
00289     {
00290     fits_clear_errmsg();
00291     status=0;
00292     planck_fail("fitshandle::get_key(): key '"+name+"' not found");
00293     }
00294   check_errors();
00295   }
00296 
00297 fitshandle::fitshandle ()
00298   : status(0), fptr(0), hdutype_(INVALID), bitpix_(INVALID), nrows_(0) {}
00299 
00300 fitshandle::~fitshandle()
00301   { clean_all(); }
00302 
00303 void fitshandle::open (const string &fname)
00304   {
00305   clean_all();
00306   fitsfile *ptr;
00307   fits_open_file(&ptr, fname.c_str(), READONLY, &status);
00308   fptr=ptr;
00309   check_errors();
00310   init_data();
00311   }
00312 
00313 void fitshandle::create (const string &fname)
00314   {
00315   clean_all();
00316   fitsfile *ptr;
00317   fits_create_file(&ptr, fname.c_str(), &status);
00318   fptr=ptr;
00319   fits_write_imghdr(FPTR, 8, 0, 0, &status); // insert empty PHDU
00320   fits_write_date(FPTR, &status);
00321   check_errors();
00322   init_data();
00323   }
00324 
00325 // static
00326 void fitshandle::delete_file (const string &name)
00327   {
00328   fitsfile *ptr;
00329   int stat = 0;
00330   fits_open_file(&ptr, name.c_str(), READWRITE, &stat);
00331   fits_delete_file(ptr, &stat);
00332   if (stat==0) return;
00333 
00334   char msg[81];
00335   fits_get_errstatus (stat, msg);
00336   cerr << msg << endl;
00337   while (fits_read_errmsg(msg)) cerr << msg << endl;
00338   planck_fail("FITS error");
00339   }
00340 
00341 string fitshandle::fileName() const
00342   {
00343   planck_assert(connected(),"handle not connected to a file");
00344   char *fname = new char[2048];
00345   fits_file_name(FPTR, fname, &status);
00346   check_errors();
00347   string result(fname);
00348   delete[] fname;
00349   return result;
00350   }
00351 
00352 void fitshandle::goto_hdu (int hdu)
00353   {
00354   int curhdu;
00355   fits_get_hdu_num(FPTR,&curhdu);
00356   if (curhdu!=hdu)
00357     {
00358     fits_movabs_hdu(FPTR, hdu, &hdutype_, &status);
00359     check_errors();
00360     init_data();
00361     }
00362   }
00363 
00364 int fitshandle::num_hdus () const
00365   {
00366   int result;
00367   fits_get_num_hdus (FPTR, &result, &status);
00368   check_errors();
00369   return result;
00370   }
00371 
00372 void fitshandle::insert_bintab (const vector<fitscolumn> &cols,
00373   const string &extname)
00374   {
00375   clean_data();
00376   int ncol=cols.size();
00377   arr2b<char> ttype(ncol,81), tform(ncol,81), tunit(ncol,81);
00378 
00379   for (long m=0; m<ncol; ++m)
00380     {
00381     strcpy (ttype[m], cols[m].name().c_str());
00382     strcpy (tunit[m], cols[m].unit().c_str());
00383     ostringstream x;
00384     x << cols[m].repcount() << type2fitschar(cols[m].type());
00385     strcpy (tform[m], x.str().c_str());
00386     }
00387   fits_insert_btbl (FPTR, nrows_, ncol, ttype.p0(), tform.p0(), tunit.p0(),
00388     const_cast<char *>(extname.c_str()), 0, &status);
00389   check_errors();
00390   init_data();
00391   }
00392 
00393 void fitshandle::insert_asctab (const vector<fitscolumn> &cols,
00394   const string &extname)
00395   {
00396   clean_data();
00397   int ncol=cols.size();
00398   arr2b<char> ttype(ncol,81), tform(ncol,81), tunit(ncol,81);
00399 
00400   for (long m=0; m<ncol; ++m)
00401     {
00402     strcpy (ttype[m], cols[m].name().c_str());
00403     strcpy (tunit[m], cols[m].unit().c_str());
00404     ostringstream x;
00405     if (cols[m].type()!=PLANCK_STRING)
00406       {
00407       planck_assert (cols[m].repcount()==1,"bad repcount for ASCII table");
00408       x << type2asciiform(cols[m].type());
00409       }
00410     else
00411       {
00412       x << "A" << dataToString(cols[m].repcount());
00413       }
00414     strcpy (tform[m], x.str().c_str());
00415     }
00416   fits_insert_atbl (FPTR, 0, nrows_, ncol, ttype.p0(), 0, tform.p0(),
00417     tunit.p0(), const_cast<char *>(extname.c_str()), &status);
00418   check_errors();
00419   init_data();
00420   }
00421 
00422 void fitshandle::insert_image (PDT type, const vector<int64> &Axes)
00423   {
00424   clean_data();
00425   arr<LONGLONG> tmpax(Axes.size());
00426   for (long m=0; m<long(Axes.size()); m++) tmpax[m]=Axes[Axes.size()-1-m];
00427   fits_insert_imgll (FPTR, type2bitpix(type), Axes.size(), &tmpax[0], &status);
00428   check_errors();
00429   init_data();
00430   }
00431 
00432 template<typename T>
00433   void fitshandle::insert_image (PDT type, const arr2<T> &data)
00434   {
00435   clean_data();
00436   arr<LONGLONG> tmpax(2);
00437   tmpax[0] = data.size2(); tmpax[1] = data.size1();
00438   fits_insert_imgll (FPTR, type2bitpix(type), 2, &tmpax[0], &status);
00439   arr2<T> &tmparr = const_cast<arr2<T> &> (data);
00440   fits_write_img (FPTR, fitsType<T>(), 1, tmpax[0]*tmpax[1],
00441     &tmparr[0][0], &status);
00442   check_errors();
00443   init_data();
00444   }
00445 
00446 template void fitshandle::insert_image (PDT type, const arr2<double> &data);
00447 template void fitshandle::insert_image (PDT type, const arr2<float> &data);
00448 
00449 void fitshandle::write_checksum()
00450   {
00451   planck_assert(connected(),"handle not connected to a file");
00452   fits_write_chksum (FPTR, &status);
00453   check_errors();
00454   }
00455 
00456 const vector<int64> &fitshandle::axes() const
00457   {
00458   planck_assert(image_hdu(),"not connected to an image");
00459   return axes_;
00460   }
00461 const string &fitshandle::colname(int i) const
00462   {
00463   planck_assert(table_hdu(i),"incorrect FITS table access");
00464   return columns_[i-1].name();
00465   }
00466 const string &fitshandle::colunit(int i) const
00467   {
00468   planck_assert(table_hdu(i),"incorrect FITS table access");
00469   return columns_[i-1].unit();
00470   }
00471 int64 fitshandle::repcount(int i) const
00472   {
00473   planck_assert(table_hdu(i),"incorrect FITS table access");
00474   return columns_[i-1].repcount();
00475   }
00476 PDT fitshandle::coltype(int i) const
00477   {
00478   planck_assert(table_hdu(i),"incorrect FITS table access");
00479   return columns_[i-1].type();
00480   }
00481 int fitshandle::ncols() const
00482   {
00483   planck_assert(table_hdu(1),"incorrect FITS table access");
00484   return columns_.size();
00485   }
00486 int64 fitshandle::nrows() const
00487   {
00488   planck_assert(table_hdu(1),"incorrect FITS table access");
00489   return nrows_;
00490   }
00491 int64 fitshandle::nelems(int i) const
00492   {
00493   planck_assert(table_hdu(i),"incorrect FITS table access");
00494   if (columns_[i-1].type()==PLANCK_STRING) return nrows_;
00495   return nrows_*columns_[i-1].repcount();
00496   }
00497 int64 fitshandle::efficientChunkSize(int i) const
00498   {
00499   planck_assert(table_hdu(1),"incorrect FITS table access");
00500   long int res;
00501   fits_get_rowsize(FPTR, &res, &status);
00502   planck_assert(res>=1,"bad recommended FITS chunk size");
00503   check_errors();
00504   return res*columns_[i-1].repcount();
00505   }
00506 
00507 void fitshandle::get_all_keys(vector<string> &keys) const
00508   {
00509   keys.clear();
00510   char card[81];
00511   const char *inclist[] = { "*" };
00512   planck_assert(connected(),"handle not connected to a file");
00513   fits_read_record (FPTR, 0, card, &status);
00514   check_errors();
00515   while (true)
00516     {
00517     fits_find_nextkey (FPTR, const_cast<char **>(inclist), 1,
00518       0, 0, card, &status);
00519     if (status!=0) break;
00520     if (fits_get_keyclass(card)==TYP_USER_KEY)
00521       {
00522       char keyname[80];
00523       int dummy;
00524       fits_get_keyname(card, keyname, &dummy, &status);
00525       check_errors();
00526       keys.push_back(trim(keyname));
00527       }
00528     check_errors();
00529     }
00530   if (status==KEY_NO_EXIST) { fits_clear_errmsg(); status=0; }
00531   check_errors();
00532   }
00533 
00534 void fitshandle::set_key_void (const string &key, const void *value,
00535   PDT type, const string &comment)
00536   {
00537   planck_assert(connected(),"handle not connected to a file");
00538   string key2 = fixkey(key);
00539   switch (type)
00540     {
00541     case PLANCK_INT8:
00542     case PLANCK_UINT8:
00543     case PLANCK_INT16:
00544     case PLANCK_INT32:
00545     case PLANCK_INT64:
00546     case PLANCK_FLOAT32:
00547     case PLANCK_FLOAT64:
00548       fits_update_key (FPTR, type2ftc(type), const_cast<char *>(key2.c_str()),
00549         const_cast<void *>(value), const_cast<char *>(comment.c_str()),
00550         &status);
00551       break;
00552     case PLANCK_BOOL:
00553       {
00554       int val = *(static_cast<const bool *>(value));
00555       fits_update_key (FPTR, TLOGICAL, const_cast<char *>(key2.c_str()),
00556         &val, const_cast<char *>(comment.c_str()), &status);
00557       break;
00558       }
00559     case PLANCK_STRING:
00560       {
00561       string val = *(static_cast<const string *>(value));
00562       fits_update_key_longstr (FPTR, const_cast<char *>(key2.c_str()),
00563         const_cast<char *>(val.c_str()), const_cast<char *>(comment.c_str()),
00564         &status);
00565       break;
00566       }
00567     default:
00568       planck_fail ("unsupported data type in set_key_void()");
00569     }
00570   check_errors();
00571   }
00572 
00573 void fitshandle::get_key_void (const string &name, void *value, PDT type) const
00574   {
00575   planck_assert(connected(),"handle not connected to a file");
00576   switch (type)
00577     {
00578     case PLANCK_INT8:
00579     case PLANCK_UINT8:
00580     case PLANCK_INT16:
00581     case PLANCK_INT32:
00582     case PLANCK_INT64:
00583     case PLANCK_FLOAT32:
00584     case PLANCK_FLOAT64:
00585       fits_read_key (FPTR, type2ftc(type), const_cast<char *>(name.c_str()),
00586         value, 0, &status);
00587       getKeyHelper(name);
00588       break;
00589     case PLANCK_BOOL:
00590       {
00591       int val;
00592       fits_read_key (FPTR, TLOGICAL, const_cast<char *>(name.c_str()), &val, 0,
00593         &status);
00594       getKeyHelper(name);
00595       *(static_cast<bool *>(value))=val;
00596       break;
00597       }
00598     case PLANCK_STRING:
00599       {
00600       char *tmp=0;
00601       fits_read_key_longstr (FPTR, const_cast<char *>(name.c_str()), &tmp, 0,
00602         &status);
00603       getKeyHelper(name);
00604       *(static_cast<string *>(value))=tmp;
00605       if (tmp) free(tmp);
00606       break;
00607       }
00608     default:
00609       planck_fail ("unsupported data type in get_key_void()");
00610     }
00611   check_errors();
00612   }
00613 
00614 void fitshandle::delete_key (const string &name)
00615   {
00616   planck_assert(connected(),"handle not connected to a file");
00617   fits_delete_key (FPTR, const_cast<char *>(name.c_str()), &status);
00618   check_errors();
00619   }
00620 
00621 void fitshandle::add_comment(const string &comment)
00622   {
00623   planck_assert(connected(),"handle not connected to a file");
00624   fits_write_comment(FPTR,const_cast<char *>(comment.c_str()),&status);
00625   check_errors();
00626   }
00627 
00628 bool fitshandle::key_present(const string &name) const
00629   {
00630   char card[81];
00631   planck_assert(connected(),"handle not connected to a file");
00632   fits_read_card(FPTR, const_cast<char *>(name.c_str()), card, &status);
00633   if (status==KEY_NO_EXIST)
00634     { fits_clear_errmsg(); status=0; return false; }
00635   check_errors();
00636   return true;
00637   }
00638 
00639 void fitshandle::assert_pdmtype (const string &pdmtype) const
00640   {
00641   string type;
00642   get_key("PDMTYPE",type);
00643   if (pdmtype==type) return;
00644   cerr << "PDMTYPE " << pdmtype << " expected, but found " << type << endl;
00645   }
00646 
00647 void fitshandle::read_column_raw_void
00648   (int colnum, void *data, PDT type, int64 num, int64 offset) const
00649   {
00650   switch (type)
00651     {
00652     case PLANCK_INT8:
00653     case PLANCK_UINT8:
00654     case PLANCK_INT16:
00655     case PLANCK_INT32:
00656     case PLANCK_INT64:
00657     case PLANCK_FLOAT32:
00658     case PLANCK_FLOAT64:
00659     case PLANCK_BOOL:
00660       read_col (colnum, data, num, type, offset); break;
00661     case PLANCK_STRING:
00662       {
00663       string *data2 = static_cast<string *> (data);
00664       planck_assert(table_hdu(colnum),"incorrect FITS table access");
00665       planck_assert (num<=(nrows_-offset),
00666         "read_column(): array too large");
00667       arr2b<char> tdata(safe_cast<tsize>(num),
00668                         safe_cast<tsize>(columns_[colnum-1].repcount()+1));
00669       int dispwidth;
00670       fits_get_col_display_width(FPTR, colnum, &dispwidth, &status);
00671       planck_assert(dispwidth<=columns_[colnum-1].repcount(),"column too wide");
00672       fits_read_col (FPTR, TSTRING, colnum, offset+1, 1, num,
00673         0, tdata.p0(), 0, &status);
00674       check_errors();
00675       for (long m=0;m<num;++m) data2[m]=tdata[m];
00676       break;
00677       }
00678     default:
00679       planck_fail ("unsupported data type in read_column_raw_void()");
00680     }
00681   }
00682 
00683 void fitshandle::write_column_raw_void
00684   (int colnum, const void *data, PDT type, int64 num, int64 offset)
00685   {
00686   switch (type)
00687     {
00688     case PLANCK_INT8:
00689     case PLANCK_UINT8:
00690     case PLANCK_INT16:
00691     case PLANCK_INT32:
00692     case PLANCK_INT64:
00693     case PLANCK_FLOAT32:
00694     case PLANCK_FLOAT64:
00695     case PLANCK_BOOL:
00696       write_col (colnum, data, num, type, offset); break;
00697     case PLANCK_STRING:
00698       {
00699       const string *data2 = static_cast<const string *> (data);
00700       planck_assert(table_hdu(colnum),"incorrect FITS table access");
00701       tsize stringlen = safe_cast<tsize>(columns_[colnum-1].repcount()+1);
00702       arr2b<char> tdata(safe_cast<tsize>(num), stringlen);
00703       for (long m=0;m<num;++m)
00704         {
00705         strncpy(tdata[m],data2[m].c_str(),stringlen-1);
00706         tdata[m][stringlen-1] = '\0';
00707         }
00708       fits_write_col (FPTR, TSTRING, colnum, offset+1, 1, num,
00709         tdata.p0(), &status);
00710       nrows_ = max(nrows_,offset+num);
00711       check_errors();
00712       break;
00713       }
00714     default:
00715       planck_fail ("unsupported data type in write_column_raw_void()");
00716     }
00717   }
00718 
00719 void fitshandle::write_image2D_void (const void *data, PDT type, tsize s1,
00720   tsize s2)
00721   {
00722   planck_assert(image_hdu(),"not connected to an image");
00723   planck_assert (axes_.size()==2, "wrong number of dimensions");
00724   planck_assert (axes_[0]==int64(s1), "wrong size of dimension 1");
00725   planck_assert (axes_[1]==int64(s2), "wrong size of dimension 2");
00726 
00727   fits_write_img (FPTR, type2ftc(type), 1, axes_[0]*axes_[1],
00728     const_cast<void *>(data), &status);
00729   check_errors();
00730   }
00731 
00732 void fitshandle::write_subimage_void (const void *data, PDT type, tsize sz,
00733   int64 offset)
00734   {
00735   planck_assert(image_hdu(),"not connected to an image");
00736   fits_write_img (FPTR, type2ftc(type), 1+offset, sz, const_cast<void *>(data),
00737     &status);
00738   check_errors();
00739   }
00740 
00741 template<typename T> void fitshandle::read_image (arr2<T> &data) const
00742   {
00743   planck_assert(image_hdu(),"not connected to an image");
00744   planck_assert (axes_.size()==2, "wrong number of dimensions");
00745   data.alloc(safe_cast<tsize>(axes_[0]), safe_cast<tsize>(axes_[1]));
00746   fits_read_img (FPTR, fitsType<T>(), 1, axes_[0]*axes_[1], 0, &data[0][0], 0,
00747     &status);
00748   check_errors();
00749   }
00750 
00751 template void fitshandle::read_image (arr2<float> &data) const;
00752 template void fitshandle::read_image (arr2<double> &data) const;
00753 
00754 template<typename T> void fitshandle::read_image (arr3<T> &data) const
00755   {
00756   planck_assert(image_hdu(),"not connected to an image");
00757   planck_assert (axes_.size()==3, "wrong number of dimensions");
00758   data.alloc(safe_cast<tsize>(axes_[0]), safe_cast<tsize>(axes_[1]),
00759     safe_cast<tsize>(axes_[2]));
00760   fits_read_img (FPTR, fitsType<T>(), 1, axes_[0]*axes_[1]*axes_[2],
00761     0, &data(0,0,0), 0, &status);
00762   check_errors();
00763   }
00764 
00765 template void fitshandle::read_image (arr3<float> &data) const;
00766 template void fitshandle::read_image (arr3<double> &data) const;
00767 
00768 template<typename T> void fitshandle::read_subimage
00769   (arr2<T> &data, int xl, int yl) const
00770   {
00771   planck_assert(image_hdu(),"not connected to an image");
00772   planck_assert (axes_.size()==2, "wrong number of dimensions");
00773   for (tsize m=0; m<data.size1(); ++m)
00774     fits_read_img (FPTR, fitsType<T>(), (xl+m)*axes_[1]+yl+1,
00775       data.size2(), 0, &data[m][0], 0, &status);
00776   check_errors();
00777   }
00778 
00779 template void fitshandle::read_subimage
00780   (arr2<float> &data, int xl, int yl) const;
00781 template void fitshandle::read_subimage
00782   (arr2<double> &data, int xl, int yl) const;
00783 
00784 void fitshandle::read_subimage_void (void *data, PDT type, tsize ndata,
00785   int64 offset) const
00786   {
00787   planck_assert(image_hdu(),"not connected to an image");
00788   fits_read_img (FPTR, type2ftc(type), 1+offset, ndata, 0, data, 0, &status);
00789   check_errors();
00790   }
00791 
00792 namespace {
00793 
00794 class cfitsio_checker
00795   {
00796   public:
00797     cfitsio_checker()
00798       {
00799       float fitsversion;
00800       planck_assert(fits_get_version(&fitsversion),
00801         "error calling fits_get_version()");
00802       int v_header  = nearest<int>(1000.*CFITSIO_VERSION),
00803           v_library = nearest<int>(1000.*fitsversion);
00804       if (v_header!=v_library)
00805         cerr << endl << "WARNING: version mismatch between CFITSIO header (v"
00806              << dataToString(v_header*0.001) << ") and linked library (v"
00807              << dataToString(v_library*0.001) << ")." << endl << endl;
00808       }
00809   };
00810 
00811 cfitsio_checker Cfitsio_Checker;
00812 
00813 } // unnamed namespace

Generated on Thu Oct 8 14:48:51 2015 for LevelS C++ support library