27 #ifndef ioutils_fits_fitsFile_hpp
28 #define ioutils_fits_fitsFile_hpp
31 #include "../../mxError.hpp"
33 #include "../../improc/eigenImage.hpp"
52 template<
typename dataT>
56 friend class fitsFile_test;
112 fitsFile(
const std::string & fname,
130 int fileName(
const std::string & fname,
148 long naxes(
int dim );
164 int open(
const std::string & fname );
208 int read( dataT * data );
216 int read( dataT * data,
226 int read( dataT * data,
227 const std::string &fname
236 int read( dataT * data,
238 const std::string &fname
242 int read( dataT * im,
243 const std::vector<std::string> & flist
247 int read( dataT * im,
248 std::vector<fitsHeader> &heads,
249 const std::vector<std::string> & flist
271 template<
typename arrT>
272 int read( arrT & data );
285 template<
typename arrT>
286 int read( arrT & data,
301 template<
typename arrT>
302 int read( arrT & data,
303 const std::string &fname
317 template<
typename arrT>
318 int read( arrT & data,
320 const std::string &fname
336 template<
typename cubeT>
337 int read( cubeT & cube,
338 const std::vector<std::string> & flist,
339 std::vector<fitsHeader> * heads = 0
353 template<
typename cubeT>
354 int read( cubeT & cube,
355 std::vector<fitsHeader> &heads,
356 const std::vector<std::string> & flist
384 const std::string &fname
394 int readHeader( std::vector<fitsHeader> & heads,
395 const std::vector<std::string> & flist
410 int write(
const dataT * im,
422 int write(
const dataT * im,
435 int write(
const dataT * im,
447 int write(
const std::string & fname,
459 int write(
const std::string & fname,
488 template<
typename arrT>
489 int write(
const std::string & fname,
507 template<
typename arrT>
508 int write(
const std::string & fname,
556 template<
typename dataT>
561 template<
typename dataT>
567 template<
typename dataT>
571 fileName(fname, doopen);
574 template<
typename dataT>
577 if(m_isOpen) close();
579 if(m_naxes)
delete[] m_naxes;
582 template<
typename dataT>
588 template<
typename dataT>
607 template<
typename dataT>
613 template<
typename dataT>
616 if(m_naxes ==
nullptr)
return -1;
618 if(dim >= m_naxis)
return -1;
623 template<
typename dataT>
633 fits_open_file(&m_fptr, m_fileName.c_str(), READONLY, &fstatus);
637 std::string explan =
"Error opening file";
639 mxError(
"fitsFile", MXE_FILEOERR, explan);
645 fits_get_img_dim(m_fptr, &m_naxis, &fstatus);
648 std::string explan =
"Error getting number of axes in file";
650 mxError(
"fitsFile", MXE_FILERERR, explan);
656 if(m_naxes)
delete[] m_naxes;
657 m_naxes =
new long[m_naxis];
659 fits_get_img_size(m_fptr, m_naxis, m_naxes, &fstatus);
662 std::string explan =
"Error getting dimensions in file";
664 mxError(
"fitsFile", MXE_FILERERR, explan);
674 template<
typename dataT>
677 return fileName(fname,
true);
680 template<
typename dataT>
689 fits_close_file(m_fptr, &fstatus);
693 std::string explan =
"Error closing file";
695 mxError(
"fitsFile", MXE_FILECERR, explan);
703 if(m_naxes)
delete[] m_naxes;
710 template<
typename dataT>
713 if(!m_isOpen or !m_naxes)
return -1;
718 template<
typename dataT>
721 if(!m_isOpen or !m_naxes)
return -1;
725 if(m_x0 > -1 && m_y0 > -1 && m_xpix > -1 && m_ypix > -1 && m_naxis ==2)
727 return m_xpix*m_ypix;
731 for(
int i=0;i<m_naxis;++i) sz*= m_naxes[i];
737 template<
typename dataT>
740 if(!m_isOpen or !m_naxes)
return -1;
742 if(m_x0 > -1 && m_y0 > -1 && m_xpix > -1 && m_ypix > -1 && m_naxis ==2)
744 if(axis == 0)
return m_xpix;
749 return m_naxes[axis];
753 template<
typename dataT>
759 *fpix =
new long[m_naxis];
760 *lpix =
new long[m_naxis];
761 *inc =
new long[m_naxis];
763 if(m_x0 > -1 && m_y0 > -1 && m_xpix > -1 && m_ypix > -1 && m_naxis == 2)
766 (*lpix)[0] = (*fpix)[0] + m_xpix-1;
768 (*lpix)[1] = (*fpix)[1] + m_ypix-1;
775 if(m_x0 < 0 && m_y0 < 0 && m_xpix < 0 && m_ypix < 0 && m_z0 < 0 && m_zframes < 0)
777 for(
int i=0;i<m_naxis; i++)
780 (*lpix)[i] = m_naxes[i];
786 if(m_x0 > -1 && m_y0 > -1 && m_xpix > -1 && m_ypix > -1)
789 (*lpix)[0] = (*fpix)[0] + m_xpix-1;
791 (*lpix)[1] = (*fpix)[1] + m_ypix-1;
799 (*lpix)[0] = m_naxes[0];
801 (*lpix)[1] = m_naxes[1];
807 if(m_z0 > -1 && m_zframes > -1)
809 (*fpix)[2] = m_z0 + 1;
810 (*lpix)[2] = (*fpix)[2] + m_zframes-1;
816 (*lpix)[2] = m_naxes[2];
827 template<
typename dataT>
834 if( open() < 0)
return -1;
837 long *fpix, *lpix, *inc;
838 pixarrs(&fpix, &lpix, &inc);
844 fits_read_subset(m_fptr, fitsType<dataT>(), fpix, lpix, inc, (
void *) &m_nulval,
845 (
void *) data, &m_anynul, &fstatus);
851 if (fstatus && fstatus != 107)
853 std::string explan =
"Error reading data from file";
855 mxError(
"fitsFile", MXE_FILERERR, explan);
862 template<
typename dataT>
867 if( read(data) < 0 )
return -1;
868 if( readHeader(head) < 0)
return -1;
873 template<
typename dataT>
875 const std::string &fname
878 if( fileName(fname) < 0 )
return -1;
879 if( read(data) < 0 )
return -1;
883 template<
typename dataT>
886 const std::string &fname
889 if( fileName(fname) < 0 )
return -1;
890 if( read(data) < 0 )
return -1;
891 if( readHeader(head) < 0 )
return -1;
895 template<
typename dataT>
897 const std::vector<std::string> & flist
900 if(flist.size() == 0)
902 mxError(
"fitsFile", MXE_PARAMNOTSET,
"Empty file list");
908 for(
int i=0;i<flist.size(); ++i)
910 if( fileName(flist[i], 1) < 0 )
return -1;
912 if( read(im + i*sz0*sz1) < 0 )
return -1;
921 template<
typename dataT>
923 std::vector<fitsHeader> &heads,
924 const std::vector<std::string> & flist
927 if(flist.size() == 0)
929 mxError(
"fitsFile", MXE_PARAMNOTSET,
"Empty file list");
935 for(
size_t i=0;i<flist.size(); ++i)
937 if( fileName(flist[i], 1) < 0 )
return -1;
939 if( read(im + i*sz0*sz1) < 0 )
return -1;
941 if( readHeader(heads[i]) < 0 )
return -1;
956 template<typename arrT, bool isCube=improc::is_eigenCube<arrT>::value>
957 struct eigenArrResize
960 void resize(arrT & arr,
int xsz,
int ysz,
int zsz)
962 arr.resize(xsz, ysz, zsz);
966 template<
typename arrT>
967 struct eigenArrResize<arrT, false>
970 void resize(arrT & arr,
int xsz,
int ysz,
int zsz)
972 static_cast<void>(zsz);
974 arr.resize(xsz, ysz);
978 template<
typename dataT>
979 template<
typename arrT>
987 if( open() < 0 )
return -1;
990 long *fpix, *lpix, *inc;
991 pixarrs(&fpix, &lpix, &inc);
993 eigenArrResize<arrT> arrresz;
996 arrresz.resize(im, lpix[0]-fpix[0]+1, lpix[1]-fpix[1]+1, lpix[2]-fpix[2]+1);
1000 arrresz.resize(im, lpix[0]-fpix[0]+1, lpix[1]-fpix[1]+1,1);
1004 arrresz.resize(im, lpix[0]-fpix[0]+1, 1,1);
1007 if( fits_read_subset(m_fptr, fitsType<typename arrT::Scalar>(), fpix, lpix, inc, (
void *) &m_nulval,
1008 (
void *) im.data(), &m_anynul, &fstatus) < 0 )
return -1;
1014 if (fstatus && fstatus != 107)
1016 std::string explan =
"Error reading data from file";
1018 mxError(
"fitsFile", MXE_FILERERR, explan);
1026 template<
typename dataT>
1027 template<
typename arrT>
1030 if( read(data) < 0 )
return -1;
1031 if( readHeader(head) < 0 )
return -1;
1035 template<
typename dataT>
1036 template<
typename arrT>
1038 const std::string &fname
1041 if( fileName(fname) < 0 )
return -1;
1042 if( read(data) < 0 )
return -1;
1046 template<
typename dataT>
1047 template<
typename arrT>
1050 const std::string &fname
1053 if( fileName(fname) < 0 )
return -1;
1054 if( read(data) < 0 )
return -1;
1055 if( readHeader(head) < 0 )
return -1;
1061 template<
typename dataT>
1062 template<
typename cubeT>
1064 const std::vector<std::string> & flist,
1065 std::vector<fitsHeader> * heads
1070 if( flist.size() == 0 )
1072 mxError(
"fitsFile", MXE_PARAMNOTSET,
"Empty file list");
1078 if( fileName(flist[0], 1) < 0)
return -1;
1080 long *fpix, *lpix, *inc;
1081 pixarrs(&fpix, &lpix, &inc);
1083 cube.resize(lpix[0]-fpix[0]+1, lpix[1]-fpix[1]+1, lpix[2]-fpix[2]+1);
1086 fits_read_subset(m_fptr, fitsType<typename cubeT::Scalar>(), fpix, lpix, inc, (
void *) &m_nulval,
1087 (
void *) cube.image(0).data(), &m_anynul, &fstatus);
1090 if (fstatus && fstatus != 107)
1093 std::string explan =
"Error reading data from file";
1096 mxError(
"cfitsio", MXE_FILERERR, explan);
1107 if( readHeader( (*heads)[0]) < 0)
return -1;
1112 for(
int i=1; i< flist.size(); ++i)
1114 fileName(flist[i], 1);
1117 fits_read_subset(m_fptr, fitsType<typename cubeT::Scalar>(), fpix, lpix, inc, (
void *) &m_nulval,
1118 (
void *) cube.image(i).data(), &m_anynul, &fstatus);
1120 if (fstatus && fstatus != 107)
1122 std::string explan =
"Error reading data from file";
1124 mxError(
"cfitsio", MXE_FILERERR, explan);
1135 if( readHeader( (*heads)[i]) < 0)
return -1;
1148 template<
typename dataT>
1149 template<
typename cubeT>
1151 std::vector<fitsHeader> & heads,
1152 const std::vector<std::string> & flist
1155 return read(cube, flist, &heads);
1158 template<
typename dataT>
1163 char keyword[FLEN_KEYWORD];
1164 char value[FLEN_VALUE];
1168 std::list<fitsHeader::headerIterator> head_keys;
1169 std::list<fitsHeader::headerIterator>::iterator head_keys_it;
1172 bool head_keys_only =
false;
1175 head_keys_only =
true;
1177 while(headIt != head.
end())
1179 head_keys.push_back(headIt);
1192 comment =
new char[FLEN_COMMENT];
1204 fits_get_hdrspace(m_fptr, &keysexist, &morekeys, &fstatus);
1208 std::string explan =
"Error reading header from file";
1210 mxError(
"fitsFile", MXE_FILERERR, explan);
1212 if(comment)
delete[] comment;
1217 for(
int i=0; i<keysexist; i++)
1219 fits_read_keyn(m_fptr, i+1, keyword, value, comment, &fstatus);
1223 std::string explan =
"Error reading header from file";
1225 mxError(
"fitsFile", MXE_FILERERR, explan);
1227 if(comment)
delete[] comment;
1234 if(strcmp(keyword,
"COMMENT") == 0)
1236 head.
append<fitsCommentType>(keyword, fitsCommentType(value), comment);
1238 else if(strcmp(keyword,
"HISTORY") == 0)
1240 head.
append<fitsHistoryType>(keyword, fitsHistoryType(value), comment);
1245 head.
append(keyword, value, comment);
1250 head_keys_it = head_keys.begin();
1251 while(head_keys_it != head_keys.end())
1253 if( (*(*head_keys_it)).keyword() == keyword)
1255 head[keyword].value(value);
1256 if(comment) head[keyword].comment(comment);
1258 head_keys.
erase(head_keys_it);
1266 if(head_keys.empty())
break;
1270 if(comment)
delete[] comment;
1275 template<
typename dataT>
1277 const std::string &fname
1280 if( fileName(fname) < 0 )
return -1;
1281 if( readHeader(head) < 0 )
return -1;
1284 template<
typename dataT>
1286 const std::vector<std::string> & flist
1289 for(
int i=0; i< flist.size(); ++i)
1291 fileName(flist[i], 1);
1293 if( readHeader( heads[i]) < 0)
return -1;
1300 template<
typename dataT>
1310 if(m_isOpen) close();
1311 if(m_naxes)
delete[] m_naxes;
1317 if(d3 > 1) m_naxis = 3;
1321 m_naxes =
new long[m_naxis];
1324 if(m_naxis > 1) m_naxes[1] = d2;
1325 if(m_naxis > 2) m_naxes[2] = d3;
1327 std::string forceFileName =
"!"+m_fileName;
1329 fits_create_file(&m_fptr, forceFileName.c_str(), &fstatus);
1332 std::string explan =
"Error creating file";
1334 mxError(
"fitsFile", MXE_FILEOERR, explan);
1340 fits_create_img( m_fptr, fitsBITPIX<dataT>(), m_naxis, m_naxes, &fstatus);
1343 std::string explan =
"Error creating image";
1345 mxError(
"fitsFile", MXE_FILEWERR, explan);
1355 LONGLONG nelements = 1;
1357 for(
int i=0;i<m_naxis;++i) nelements *= m_naxes[i];
1359 fits_write_pix( m_fptr, fitsType<dataT>(), fpixel, nelements, (
void *) im, &fstatus);
1362 std::string explan =
"Error writing data";
1364 mxError(
"fitsFile", MXE_FILEWERR, explan);
1374 for(it = head->
begin(); it != head->
end(); ++it)
1376 int wrv = it->write(m_fptr);
1379 std::string explan =
"Error writing keyword";
1381 mxError(
"fitsFile", MXE_FILEWERR, explan);
1387 if( close() < 0)
return -1;
1392 template<
typename dataT>
1399 return write(im, d1, d2, d3, (
fitsHeader *) 0);
1402 template<
typename dataT>
1409 return write(im, d1, d2, d3, &head);
1413 template<
typename dataT>
1421 if( fileName(fname,
false) < 0)
return -1;
1422 return write(im, d1, d2, d3, (
fitsHeader *) 0);
1425 template<
typename dataT>
1433 if( fileName(fname,
false) < 0)
return -1;
1434 return write(im, d1, d2, d3, &head);
1439 template<
typename dataT>
1440 template<
typename arrT>
1447 return write(fname, im.data(), im.rows(), im.cols(), planes(im));
1451 template<
typename dataT>
1452 template<
typename arrT>
1459 return write(fname, im.data(), im.rows(), im.cols(), planes(im), head);
1463 template<
typename dataT>
1472 template<
typename dataT>
1485 template<
typename dataT>
1492 template<
typename dataT>
1498 m_zframes = zframes;
Class to manage interactions with a FITS file.
long * m_naxes
The size of each dimension.
int write(const dataT *im, int d1, int d2, int d3, fitsHeader *head)
Write the contents of a raw array to the FITS file.
long naxes(int dim)
Get the current value of m_naxes for the specified dimension.
dataT m_nulval
The value to replace null values with.
long m_zframes
The number of frames to read from a cube.
int open()
Open the file and gets its dimensions.
long getSize()
Get the total size.
int readHeader(fitsHeader &head)
Read the header from the fits file.
void pixarrs(long **fpix, long **lpix, long **inc)
Fill in the read-size arrays for reading a subset (always used)
void setReadSize()
Set to read all the pixels in the file.
long m_ypix
The number of y-pixels to read.
fitsFile()
Default constructor.
long m_z0
The starting frame to read from a cube.
long m_y0
The starting y-pixel to read from.
void setCubeReadSize()
Set to read all frames from a cube.
int getDimensions()
Get the number of dimensions (i.e. m_naxis)
int m_naxis
The dimensions of the image (1D, 2D, 3D etc)
int m_noComment
Flag to control whether the comment string is read.
int m_anynul
Records whether any null values were replaced.
void construct()
One time initialization common to all constructors.
int naxis()
Get the current value of m_naxis.
fitsfile * m_fptr
The cfitsio data structure.
std::string m_fileName
The path to the file.
long m_x0
The starting x-pixel to read from.
long m_xpix
The number of x-pixels to read.
std::string fileName()
Get the current value of m_fileName.
bool m_isOpen
Flag indicating whether the file is open or not.
int close()
Close the file.
int read(dataT *data)
Read the contents of the FITS file into an array.
Declares and defines utilities to work with FITS files.
fitsFile< long > fitsFilel
A fitsFile to work in signed long integers.
fitsFile< unsigned short > fitsFileus
A fitsFile to work in unsigned short integers.
fitsFile< short > fitsFiles
A fitsFile to work in signed short integers.
fitsFile< char > fitsFilec
A fitsFile to work in signed characters.
fitsFile< int > fitsFilei
A fitsFile to work in signed integers.
fitsFile< unsigned char > fitsFileuc
A fitsFile to work in unsigned characters.
fitsFile< unsigned int > fitsFileui
A fitsFile to work in unsigned integers.
fitsFile< double > fitsFiled
A fitsFile to work in double precision.
fitsFile< float > fitsFilef
A fitsFile to work in single precision floats.
void fitsErrText(std::string &explan, const std::string &filename, int fstatus)
Generate a rich error meesage from a FITS status code.
Function object to return the number of planes for any Eigen like object, whether 2D or a 3D cube.