27#ifndef ioutils_fits_fitsFile_hpp
28#define ioutils_fits_fitsFile_hpp
30#include "../../mxError.hpp"
32#include "../../improc/eigenImage.hpp"
50template <
typename dataT>
54 friend class fitsFile_test;
125 int fileName(
const std::string &fname,
143 long naxes(
int dim );
159 int open(
const std::string &fname );
200 int read( dataT *data );
208 int read( dataT *data,
218 int read( dataT *data,
219 const std::string &fname
228 int read( dataT *data,
230 const std::string &fname
235 const std::vector<std::string> &flist
241 std::vector<fitsHeader> &heads,
242 const std::vector<std::string> &flist
263 template <
typename arrT>
278 template <
typename arrT>
279 int read( arrT &data,
294 template <
typename arrT>
295 int read( arrT &data,
296 const std::string &fname
310 template <
typename arrT>
311 int read( arrT &data,
313 const std::string &fname
329 template <
typename cubeT>
330 int read( cubeT &cube,
331 const std::vector<std::string> &flist,
332 std::vector<fitsHeader> *heads =
347 template <
typename cubeT>
348 int read( cubeT &cube,
349 std::vector<fitsHeader> &heads,
350 const std::vector<std::string> &flist
376 const std::string &fname
387 std::vector<fitsHeader> &heads,
388 const std::vector<std::string> &flist
403 int write(
const dataT *im,
415 int write(
const dataT *im,
428 int write(
const dataT *im,
440 int write(
const std::string &fname,
452 int write(
const std::string &fname,
481 template <
typename arrT>
482 int write(
const std::string &fname,
500 template <
typename arrT>
501 int write(
const std::string &fname,
548template <
typename dataT>
553template <
typename dataT>
559template <
typename dataT>
563 fileName( fname, doopen );
566template <
typename dataT>
576template <
typename dataT>
582template <
typename dataT>
600template <
typename dataT>
606template <
typename dataT>
609 if( m_naxes ==
nullptr )
618template <
typename dataT>
628 fits_open_file( &m_fptr, m_fileName.c_str(), READONLY, &fstatus );
632 std::string explan =
"Error opening file";
635 mxThrowException(
err::liberr,
"fitsFile::open", explan);
640 fits_get_img_dim( m_fptr, &m_naxis, &fstatus );
643 std::string explan =
"Error getting number of axes in file";
646 mxThrowException(
err::liberr,
"fitsFile::open", explan);
653 m_naxes =
new long[m_naxis];
655 fits_get_img_size( m_fptr, m_naxis, m_naxes, &fstatus );
658 std::string explan =
"Error getting dimensions in file";
661 mxThrowException(
err::liberr,
"fitsFile::open", explan);
671template <
typename dataT>
674 return fileName( fname,
true );
677template <
typename dataT>
686 fits_close_file( m_fptr, &fstatus );
690 std::string explan =
"Error closing file";
693 mxThrowException(
err::liberr,
"fitsFile::close", explan);
709template <
typename dataT>
712 if( !m_isOpen or !m_naxes )
718template <
typename dataT>
721 if( !m_isOpen or !m_naxes )
726 if( m_x0 > -1 && m_y0 > -1 && m_xpix > -1 && m_ypix > -1 && m_naxis == 2 )
728 return m_xpix * m_ypix;
732 for(
int i = 0; i < m_naxis; ++i )
739template <
typename dataT>
742 if( !m_isOpen or !m_naxes )
745 if( m_x0 > -1 && m_y0 > -1 && m_xpix > -1 && m_ypix > -1 && m_naxis == 2 )
753 return m_naxes[axis];
757template <
typename dataT>
760 *fpix =
new long[m_naxis];
761 *lpix =
new long[m_naxis];
762 *inc =
new long[m_naxis];
764 if( m_x0 > -1 && m_y0 > -1 && m_xpix > -1 && m_ypix > -1 && m_naxis == 2 )
766 ( *fpix )[0] = m_x0 + 1;
767 ( *lpix )[0] = ( *fpix )[0] + m_xpix - 1;
768 ( *fpix )[1] = m_y0 + 1;
769 ( *lpix )[1] = ( *fpix )[1] + m_ypix - 1;
776 if( m_x0 < 0 && m_y0 < 0 && m_xpix < 0 && m_ypix < 0 && m_z0 < 0 && m_zframes < 0 )
778 for(
int i = 0; i < m_naxis; i++ )
781 ( *lpix )[i] = m_naxes[i];
787 if( m_x0 > -1 && m_y0 > -1 && m_xpix > -1 && m_ypix > -1 )
789 ( *fpix )[0] = m_x0 + 1;
790 ( *lpix )[0] = ( *fpix )[0] + m_xpix - 1;
791 ( *fpix )[1] = m_y0 + 1;
792 ( *lpix )[1] = ( *fpix )[1] + m_ypix - 1;
800 ( *lpix )[0] = m_naxes[0];
802 ( *lpix )[1] = m_naxes[1];
808 if( m_z0 > -1 && m_zframes > -1 )
810 ( *fpix )[2] = m_z0 + 1;
811 ( *lpix )[2] = ( *fpix )[2] + m_zframes - 1;
817 ( *lpix )[2] = m_naxes[2];
828template <
typename dataT>
839 long *fpix, *lpix, *inc;
840 pixarrs( &fpix, &lpix, &inc );
847 m_fptr, fitsType<dataT>(), fpix, lpix, inc, (
void *)&m_nulval, (
void *)data, &m_anynul, &fstatus );
853 if( fstatus && fstatus != 107 )
855 std::string explan =
"Error reading data from file";
858 mxThrowException(
err::liberr,
"fitsFile::read", explan);
866template <
typename dataT>
869 if( read( data ) < 0 )
871 if( readHeader( head ) < 0 )
877template <
typename dataT>
880 if( fileName( fname ) < 0 )
882 if( read( data ) < 0 )
887template <
typename dataT>
890 if( fileName( fname ) < 0 )
892 if( read( data ) < 0 )
894 if( readHeader( head ) < 0 )
899template <
typename dataT>
902 if( flist.size() == 0 )
909 long sz0 = 0, sz1 = 0;
911 for(
int i = 0; i < flist.size(); ++i )
913 if( fileName( flist[i], 1 ) < 0 )
916 if( read( im + i * sz0 * sz1 ) < 0 )
926template <
typename dataT>
929 if( flist.size() == 0 )
935 long sz0 = 0, sz1 = 0;
937 for(
size_t i = 0; i < flist.size(); ++i )
939 if( fileName( flist[i], 1 ) < 0 )
942 if( read( im + i * sz0 * sz1 ) < 0 )
945 if( readHeader( heads[i] ) < 0 )
959template <typename arrT, bool isCube = improc::is_eigenCube<arrT>::value>
963 void resize( arrT &arr,
int xsz,
int ysz,
int zsz )
965 arr.resize( xsz, ysz, zsz );
969template <
typename arrT>
970struct eigenArrResize<arrT, false>
973 void resize( arrT &arr,
int xsz,
int ysz,
int zsz )
975 static_cast<void>( zsz );
977 arr.resize( xsz, ysz );
981template <
typename dataT>
982template <
typename arrT>
995 long *fpix, *lpix, *inc;
996 pixarrs( &fpix, &lpix, &inc );
998 eigenArrResize<arrT> arrresz;
1001 arrresz.resize( im, lpix[0] - fpix[0] + 1, lpix[1] - fpix[1] + 1, lpix[2] - fpix[2] + 1 );
1003 else if( m_naxis > 1 )
1005 arrresz.resize( im, lpix[0] - fpix[0] + 1, lpix[1] - fpix[1] + 1, 1 );
1009 arrresz.resize( im, lpix[0] - fpix[0] + 1, 1, 1 );
1012 if( fits_read_subset( m_fptr,
1013 fitsType<typename arrT::Scalar>(),
1027 if( fstatus && fstatus != 107 )
1029 std::string explan =
"Error reading data from file";
1032 mxThrowException(
err::liberr,
"fitsFile::read", explan);
1039template <
typename dataT>
1040template <
typename arrT>
1043 if( read( data ) < 0 )
1045 if( readHeader( head ) < 0 )
1050template <
typename dataT>
1051template <
typename arrT>
1054 if( fileName( fname ) < 0 )
1056 if( read( data ) < 0 )
1061template <
typename dataT>
1062template <
typename arrT>
1065 if( fileName( fname ) < 0 )
1067 if( read( data ) < 0 )
1069 if( readHeader( head ) < 0 )
1075template <
typename dataT>
1076template <
typename cubeT>
1081 if( flist.size() == 0 )
1089 if( fileName( flist[0], 1 ) < 0 )
1092 long *fpix, *lpix, *inc;
1093 pixarrs( &fpix, &lpix, &inc );
1095 cube.resize( lpix[0] - fpix[0] + 1, lpix[1] - fpix[1] + 1, flist.size() );
1098 fits_read_subset( m_fptr,
1099 fitsType<typename cubeT::Scalar>(),
1104 (
void *)cube.image( 0 ).data(),
1108 if( fstatus && fstatus != 107 )
1111 std::string explan =
"error reading data from file";
1115 mxThrowException(
err::liberr,
"fitsFile::read", explan);
1126 if( readHeader( ( *heads )[0] ) < 0 )
1131 for(
int i = 1; i < flist.size(); ++i )
1133 fileName( flist[i], 1 );
1136 fits_read_subset( m_fptr,
1137 fitsType<typename cubeT::Scalar>(),
1142 (
void *)cube.image( i ).data(),
1146 if( fstatus && fstatus != 107 )
1148 std::string explan =
"Error reading data from file";
1151 mxThrowException(
err::liberr,
"fitsFile::read", explan);
1162 if( readHeader( ( *heads )[i] ) < 0 )
1174template <
typename dataT>
1175template <
typename cubeT>
1178 return read( cube, flist, &heads );
1181template <
typename dataT>
1186 char keyword[FLEN_KEYWORD];
1187 char value[FLEN_VALUE];
1191 std::list<fitsHeader::headerIterator> head_keys;
1192 std::list<fitsHeader::headerIterator>::iterator head_keys_it;
1195 bool head_keys_only =
false;
1196 if( head.
size() > 0 )
1198 head_keys_only =
true;
1200 while( headIt != head.
end() )
1202 head_keys.push_back( headIt );
1215 comment =
new char[FLEN_COMMENT];
1227 fits_get_hdrspace( m_fptr, &keysexist, &morekeys, &fstatus );
1231 std::string explan =
"Error reading header from file";
1234 mxThrowException(
err::liberr,
"fitsFile::readHeader", explan);
1242 for(
int i = 0; i < keysexist; i++ )
1244 fits_read_keyn( m_fptr, i + 1, keyword, value, comment, &fstatus );
1248 std::string explan =
"Error reading header from file";
1251 mxThrowException(
err::liberr,
"fitsFile::readHeader", explan);
1259 if( !head_keys_only )
1261 if( strcmp( keyword,
"COMMENT" ) == 0 )
1263 head.
append<fitsCommentType>( keyword, fitsCommentType( value ), comment );
1265 else if( strcmp( keyword,
"HISTORY" ) == 0 )
1267 head.
append<fitsHistoryType>( keyword, fitsHistoryType( value ), comment );
1272 head.
append( keyword, value, comment );
1277 head_keys_it = head_keys.begin();
1278 while( head_keys_it != head_keys.end() )
1280 if( ( *( *head_keys_it ) ).keyword() == keyword )
1282 head[keyword].value( value );
1284 head[keyword].comment( comment );
1286 head_keys.
erase( head_keys_it );
1294 if( head_keys.empty() )
1305template <
typename dataT>
1308 if( fileName( fname ) < 0 )
1310 if( readHeader( head ) < 0 )
1314template <
typename dataT>
1317 for(
int i = 0; i < flist.size(); ++i )
1319 fileName( flist[i], 1 );
1321 if( readHeader( heads[i] ) < 0 )
1328template <
typename dataT>
1348 m_naxes =
new long[m_naxis];
1356 std::string forceFileName =
"!" + m_fileName;
1358 fits_create_file( &m_fptr, forceFileName.c_str(), &fstatus );
1361 std::string explan =
"Error creating file";
1364 mxThrowException(
err::liberr,
"fitsFile::write", explan);
1370 fits_create_img( m_fptr, fitsBITPIX<dataT>(), m_naxis, m_naxes, &fstatus );
1373 std::string explan =
"Error creating image";
1376 mxThrowException(
err::liberr,
"fitsFile::readHeader", explan);
1386 LONGLONG nelements = 1;
1388 for(
int i = 0; i < m_naxis; ++i )
1389 nelements *= m_naxes[i];
1391 fits_write_pix( m_fptr, fitsType<dataT>(), fpixel, nelements, (
void *)im, &fstatus );
1394 std::string explan =
"Error writing data";
1397 mxThrowException(
err::liberr,
"fitsFile::write", explan);
1406 for( it = head->
begin(); it != head->
end(); ++it )
1408 int wrv = it->write( m_fptr );
1411 std::string explan =
"Error writing keyword";
1414 mxThrowException(
err::liberr,
"fitsFile::write", explan);
1425template <
typename dataT>
1428 return write( im, d1, d2, d3, (
fitsHeader *)0 );
1431template <
typename dataT>
1434 return write( im, d1, d2, d3, &head );
1437template <
typename dataT>
1440 if( fileName( fname,
false ) < 0 )
1442 return write( im, d1, d2, d3, (
fitsHeader *)0 );
1445template <
typename dataT>
1448 if( fileName( fname,
false ) < 0 )
1450 return write( im, d1, d2, d3, &head );
1453template <
typename dataT>
1454template <
typename arrT>
1459 return write( fname, im.data(), im.rows(), im.cols(), planes( im ) );
1462template <
typename dataT>
1463template <
typename arrT>
1468 return write( fname, im.data(), im.rows(), im.cols(), planes( im ), head );
1471template <
typename dataT>
1480template <
typename dataT>
1489template <
typename dataT>
1496template <
typename dataT>
1500 m_zframes = zframes;
mxException for errors returned by a library call
mxException for parameters which aren't set
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.