27#ifndef ioutils_fits_fitsFile_hpp
28#define ioutils_fits_fitsFile_hpp
44namespace fitsFileDetail
49struct fitsFileCfitsioOps
51 int ( *openFile )( fitsfile **,
const char *, int,
int * );
52 decltype( &ffgidm ) getImageDim;
53 decltype( &ffgisz ) getImageSize;
54 decltype( &ffclos ) closeFile;
55 decltype( &ffgsv ) readSubset;
56 decltype( &ffghsp ) getHeaderSpace;
57 decltype( &ffgkyn ) readKey;
58 decltype( &ffinit ) createFile;
59 decltype( &ffcrim ) createImage;
60 decltype( &ffppx ) writePixels;
61 long *( *allocateLongs )( size_t );
65fitsFileCfitsioOps &fitsFileCfitsioOpsInstance();
68void resetFitsFileCfitsioOps();
82template <
typename dataT,
class verboseT = verbose::d>
86 friend class fitsFile_test;
246 long *fpix{
nullptr };
247 long *lpix{
nullptr };
248 long *inc{
nullptr };
277 fpix = fitsFileDetail::fitsFileCfitsioOpsInstance().allocateLongs(
naxis );
278 lpix = fitsFileDetail::fitsFileCfitsioOpsInstance().allocateLongs(
naxis );
279 inc = fitsFileDetail::fitsFileCfitsioOpsInstance().allocateLongs(
naxis );
281 catch(
const std::bad_alloc &e )
284 std::string(
"allocating pixel read arrays: " ) + e.what() );
285#ifdef MXLIB_TRAP_ALLOC_ERRORS
291 catch(
const std::exception &e )
294 std::string(
"allocating pixel read arrays: " ) + e.what() );
295#ifdef MXLIB_TRAP_ALLOC_ERRORS
304#ifdef MXLIB_TRAP_ALLOC_ERRORS
312 if( fpix ==
nullptr )
317 if( lpix ==
nullptr )
380 const std::string &fname
391 const std::string &fname
396 const std::vector<std::string> &flist
403 const std::vector<std::string> &flist
424 template <
typename arrT>
439 template <
typename arrT>
456 template <
typename arrT>
459 const std::string &fname
473 template <
typename arrT>
477 const std::string &fname
493 template <
typename cubeT>
495 const std::vector<std::string> &flist,
511 template <
typename cubeT>
516 const std::vector<std::string> &flist
542 const std::string &fname
554 const std::vector<std::string> &flist
647 template <
typename arrT>
666 template <
typename arrT>
711template <
typename dataT,
class verboseT>
716template <
typename dataT,
class verboseT>
722template <
typename dataT,
class verboseT>
729template <
typename dataT,
class verboseT>
737template <
typename dataT,
class verboseT>
745template <
typename dataT,
class verboseT>
754template <
typename dataT,
class verboseT>
760template <
typename dataT,
class verboseT>
778template <
typename dataT,
class verboseT>
784template <
typename dataT,
class verboseT>
787 if( dim >=
m_naxis || dim > 2 )
795template <
typename dataT,
class verboseT>
810 fitsFileDetail::fitsFileCfitsioOpsInstance().openFile( &
m_fptr,
m_fileName.c_str(), READONLY, &fstatus );
818 fitsFileDetail::fitsFileCfitsioOpsInstance().getImageDim(
m_fptr, &
m_naxis, &fstatus );
822 ffclos(
m_fptr, &closeStatus );
825 "Getting number of axes in file " +
m_fileName );
829 fitsFileDetail::fitsFileCfitsioOpsInstance().getImageSize(
m_fptr,
m_naxis,
m_naxes, &fstatus );
833 ffclos(
m_fptr, &closeStatus );
844template <
typename dataT,
class verboseT>
850template <
typename dataT,
class verboseT>
859 fitsFileDetail::fitsFileCfitsioOpsInstance().closeFile(
m_fptr, &fstatus );
872template <
typename dataT,
class verboseT>
884template <
typename dataT,
class verboseT>
911 for(
int i = 0; i <
m_naxis && i < 3; ++i )
920template <
typename dataT,
class verboseT>
929 if( axis >=
m_naxis || axis > 2 )
955template <
typename dataT,
class verboseT>
968 pixarr.fpix[0] =
m_x0 + 1;
969 pixarr.lpix[0] = pixarr.fpix[0] +
m_xpix - 1;
980 pixarr.fpix[0] =
m_x0 + 1;
981 pixarr.lpix[0] = pixarr.fpix[0] +
m_xpix - 1;
982 pixarr.fpix[1] =
m_y0 + 1;
983 pixarr.lpix[1] = pixarr.fpix[1] +
m_ypix - 1;
992 for(
int i = 0; i <
m_naxis && i < 3; i++ )
1003 pixarr.fpix[0] =
m_x0 + 1;
1004 pixarr.lpix[0] = pixarr.fpix[0] +
m_xpix - 1;
1005 pixarr.fpix[1] =
m_y0 + 1;
1006 pixarr.lpix[1] = pixarr.fpix[1] +
m_ypix - 1;
1024 pixarr.fpix[2] =
m_z0 + 1;
1025 pixarr.lpix[2] = pixarr.fpix[2] +
m_zframes - 1;
1044template <
typename dataT,
class verboseT>
1060 fitsFileDetail::fitsFileCfitsioOpsInstance().readSubset(
m_fptr,
1070 if( fstatus && fstatus != END_OF_FILE )
1079template <
typename dataT,
class verboseT>
1087template <
typename dataT,
class verboseT>
1095template <
typename dataT,
class verboseT>
1105template <
typename dataT,
class verboseT>
1108 if( flist.size() == 0 )
1113 long sz0 = 0, sz1 = 0;
1115 for(
int i = 0; i < flist.size(); ++i )
1132template <
typename dataT,
class verboseT>
1135 const std::vector<std::string> &flist )
1137 if( flist.size() == 0 )
1142 if( heads.size() != flist.size() )
1145 "Header vector is not the same size as the file list" );
1148 long sz0 = 0, sz1 = 0;
1150 for(
size_t i = 0; i < flist.size(); ++i )
1174template <typename arrT, class verboseT, bool isCube = improc::is_eigenCube<arrT>::value>
1175struct eigenArrResize
1178 error_t resize( arrT &arr,
int xsz,
int ysz,
int zsz )
1182 arr.resize( xsz, ysz, zsz );
1184 catch(
const std::bad_alloc &e )
1187 std::string(
"resizing array: " ) + e.what() );
1188#ifdef MXLIB_TRAP_ALLOC_ERRORS
1194 catch(
const std::exception &e )
1197 std::string(
"resizing array: " ) + e.what() );
1198#ifdef MXLIB_TRAP_ALLOC_ERRORS
1207#ifdef MXLIB_TRAP_ALLOC_ERRORS
1218template <
typename arrT,
class verboseT>
1219struct eigenArrResize<arrT, verboseT, false>
1222 error_t resize( arrT &arr,
int xsz,
int ysz, [[maybe_unused]]
int zsz )
1226 arr.resize( xsz, ysz );
1228 catch(
const std::bad_alloc &e )
1231 std::string(
"resizing array: " ) + e.what() );
1232#ifdef MXLIB_TRAP_ALLOC_ERRORS
1238 catch(
const std::exception &e )
1241 std::string(
"resizing array: " ) + e.what() );
1242#ifdef MXLIB_TRAP_ALLOC_ERRORS
1251#ifdef MXLIB_TRAP_ALLOC_ERRORS
1262template <
typename dataT,
class verboseT>
1263template <
typename arrT>
1278 eigenArrResize<arrT, verboseT> arrresz;
1282 pixarrs.lpix[0] - pixarrs.fpix[0] + 1,
1283 pixarrs.lpix[1] - pixarrs.fpix[1] + 1,
1284 pixarrs.lpix[2] - pixarrs.fpix[2] + 1 ) );
1289 arrresz.resize( im, pixarrs.lpix[0] - pixarrs.fpix[0] + 1, pixarrs.lpix[1] - pixarrs.fpix[1] + 1, 1 ) );
1293 mxlib_error_check( arrresz.resize( im, pixarrs.lpix[0] - pixarrs.fpix[0] + 1, 1, 1 ) );
1296 fitsFileDetail::fitsFileCfitsioOpsInstance().readSubset(
m_fptr,
1306 if( fstatus && fstatus != END_OF_FILE )
1315template <
typename dataT,
class verboseT>
1316template <
typename arrT>
1320 errc =
read( data );
1335template <
typename dataT,
class verboseT>
1336template <
typename arrT>
1346 errc =
read( data );
1354template <
typename dataT,
class verboseT>
1355template <
typename arrT>
1365 errc =
read( data );
1380template <
typename dataT,
class verboseT>
1381template <
typename cubeT>
1383 const std::vector<std::string> &flist,
1389 if( flist.size() == 0 )
1394 if( heads && heads->size() != flist.size() )
1397 "Header vector is not the same size as the file list" );
1415 cube.resize( pixarrs.lpix[0] - pixarrs.fpix[0] + 1, pixarrs.lpix[1] - pixarrs.fpix[1] + 1, flist.size() );
1418 fitsFileDetail::fitsFileCfitsioOpsInstance().readSubset(
m_fptr,
1424 (
void *)cube.image( 0 ).data(),
1428 if( fstatus && fstatus != END_OF_FILE )
1444 for(
int i = 1; i < flist.size(); ++i )
1453 fitsFileDetail::fitsFileCfitsioOpsInstance().readSubset(
m_fptr,
1459 (
void *)cube.image( i ).data(),
1463 if( fstatus && fstatus != END_OF_FILE )
1482template <
typename dataT,
class verboseT>
1483template <
typename cubeT>
1486 const std::vector<std::string> &flist )
1491template <
typename dataT,
class verboseT>
1496 char keyword[FLEN_KEYWORD];
1497 char value[FLEN_VALUE];
1498 std::unique_ptr<char[]> commentStorage;
1499 char *comment =
nullptr;
1502 typename std::list<headerIteratorT> head_keys;
1503 typename std::list<headerIteratorT>::iterator head_keys_it;
1506 bool head_keys_only =
false;
1507 if( head.
size() > 0 )
1509 head_keys_only =
true;
1510 headerIteratorT headIt = head.
begin();
1511 while( headIt != head.
end() )
1513 head_keys.push_back( headIt );
1526 commentStorage = std::make_unique<char[]>( FLEN_COMMENT );
1527 comment = commentStorage.get();
1539 fitsFileDetail::fitsFileCfitsioOpsInstance().getHeaderSpace(
m_fptr, &keysexist, &morekeys, &fstatus );
1547 for(
int i = 0; i < keysexist; i++ )
1549 fitsFileDetail::fitsFileCfitsioOpsInstance().readKey(
m_fptr, i + 1, keyword, value, comment, &fstatus );
1557 if( !head_keys_only )
1559 if( strcmp( keyword,
"COMMENT" ) == 0 )
1561 head.template append<fitsCommentType>( keyword, fitsCommentType( value ), comment );
1563 else if( strcmp( keyword,
"HISTORY" ) == 0 )
1565 head.template append<fitsHistoryType>( keyword, fitsHistoryType( value ), comment );
1570 head.
append( keyword, value, comment );
1575 head_keys_it = head_keys.begin();
1576 while( head_keys_it != head_keys.end() )
1578 if( ( *( *head_keys_it ) ).keyword() == keyword )
1580 head[keyword].value( (
const char *)value );
1583 head[keyword].comment( comment );
1586 head_keys.
erase( head_keys_it );
1594 if( head_keys.empty() )
1604template <
typename dataT,
class verboseT>
1613template <
typename dataT,
class verboseT>
1615 const std::vector<std::string> &flist )
1617 if( heads.size() != 0 && heads.size() != flist.size() )
1620 "head vector is not empty and not same size as file list" );
1623 if( heads.size() == 0 )
1625 heads.resize( flist.size() );
1629 for(
int i = 0; i < flist.size(); ++i )
1639template <
typename dataT,
class verboseT>
1672 std::string forceFileName =
"!" +
m_fileName;
1674 fitsFileDetail::fitsFileCfitsioOpsInstance().createFile( &
m_fptr, forceFileName.c_str(), &fstatus );
1694 LONGLONG nelements = 1;
1696 for(
int i = 0; i <
m_naxis && i < 3; ++i )
1702 fitsFileDetail::fitsFileCfitsioOpsInstance()
1713 for( it = head->
begin(); it != head->
end(); ++it )
1726template <
typename dataT,
class verboseT>
1732template <
typename dataT,
class verboseT>
1738template <
typename dataT,
class verboseT>
1746template <
typename dataT,
class verboseT>
1748 const std::string &fname,
const dataT *im,
int d1,
int d2,
int d3,
fitsHeader<verboseT> &head )
1755template <
typename dataT,
class verboseT>
1756template <
typename arrT>
1764template <
typename dataT,
class verboseT>
1765template <
typename arrT>
1770 return write( fname, im.data(), im.rows(), im.cols(), planes( im ), head );
1773template <
typename dataT,
class verboseT>
1782template <
typename dataT,
class verboseT>
1791template <
typename dataT,
class verboseT>
1798template <
typename dataT,
class verboseT>
Class to manage interactions with a FITS file.
error_t readHeader(fitsHeader< verboseT > &head, const std::string &fname)
Read the header from the fits file.
int naxis()
Get the current value of m_naxis.
error_t read(dataT *data, const std::string &fname)
Read the contents of the FITS file into an array.
fitsFile(const std::string &fname, error_t &errc)
Constructor with file name and error code.
error_t open(const std::string &fname)
Open the file, first setting the file path.
long getSize(error_t &errc)
Get the total size.
error_t write(const std::string &fname, const arrT &im)
Write the contents of an Eigen-type array to a FITS file.
void setCubeReadSize()
Set to read all frames from a cube.
error_t read(arrT &data, const std::string &fname)
Read the contents of the FITS file into an Eigen array type (not a simple pointer).
long naxes(int dim)
Get the current value of m_naxes for the specified dimension.
error_t open()
Open the file and gets its dimensions.
std::string fileName()
Get the current value of m_fileName.
error_t read(dataT *im, const std::vector< std::string > &flist)
Read data from a vector list of files into an image cube.
error_t write(const dataT *im, int d1, int d2, int d3)
Write the contents of a raw array to the FITS file.
int getDimensions(error_t &errc)
Get the number of dimensions (i.e. m_naxis).
error_t read(arrT &data, fitsHeader< verboseT > &head, const std::string &fname)
Read the contents of the FITS file into an Eigen array type (not a simple pointer).
error_t read(arrT &data, fitsHeader< verboseT > &head)
Read the contents of the FITS file into an Eigen array type (not a simple pointer).
error_t read(dataT *im, std::vector< fitsHeader< verboseT > > &heads, const std::vector< std::string > &flist)
Read data from a vector of files into an image cube with individual headers.
void setReadSize()
Set to read all the pixels in the file.
error_t write(const std::string &fname, const dataT *im, int d1, int d2, int d3, fitsHeader< verboseT > &head)
Write the contents of a raw array to the FITS file.
error_t write(const dataT *im, int d1, int d2, int d3, fitsHeader< verboseT > &head)
Write the contents of a raw array to the FITS file.
fitsFile()
Default constructor.
void setCubeReadSize(long z0, long zframes)
Set the number of frames to read from a cube.
fitsFile(error_t &errc)
Default constructor with error code.
error_t write(const std::string &fname, const arrT &im, fitsHeader< verboseT > &head)
Write the contents of an Eigen-type array to a FITS file.
fitsFile(const std::string &fname, bool doopen=true)
Constructor with file name, and option to open.
error_t write(const std::string &fname, const dataT *im, int d1, int d2, int d3)
Write the contents of a raw array to the FITS file.
error_t readHeader(std::vector< fitsHeader< verboseT > > &heads, const std::vector< std::string > &flist)
Read the headers from a list of FITS files.
error_t fileName(const std::string &fname, bool doopen=true)
Set the file path, and optionally open the file.
error_t read(cubeT &cube, std::vector< fitsHeader< verboseT > > &heads, const std::vector< std::string > &flist)
Read data from a vector of files into an image cube with individual headers.
error_t close()
Close the file.
void setReadSize(long x0, long y0, long xpix, long ypix)
Set to read only a subset of the pixels in the file.
error_t readHeader(fitsHeader< verboseT > &head)
Read the header from the fits file.
error_t calcPixarrs(pixarrT &pixarr)
Fill in the read-size arrays for reading a subset (always used).
error_t read(dataT *data, fitsHeader< verboseT > &head)
Read the contents of the FITS file into an array.
error_t read(dataT *data, fitsHeader< verboseT > &head, const std::string &fname)
Read the contents of the FITS file into an array and read the header.
error_t read(arrT &data)
Read the contents of the FITS file into an Eigen array type (not a simple pointer).
fitsFile(const std::string &fname, bool doopen, error_t &errc)
Constructor with file name, option to open, and error code.
error_t read(dataT *data)
Read the contents of the FITS file into an array.
void construct()
One time initialization common to all constructors.
long getSize(size_t axis, error_t &errc)
Get the size of a specific dimension.
error_t write(const dataT *im, int d1, int d2, int d3, fitsHeader< verboseT > *head)
Write the contents of a raw array to the FITS file.
error_t read(cubeT &cube, const std::vector< std::string > &flist, std::vector< fitsHeader< verboseT > > *heads=0)
Read data from a vector list of files into an image cube.
Tools for using the eigen library for image processing.
Declares and defines utilities to work with FITS files.
error_t
The mxlib error codes.
@ noerror
No error has occurred.
@ std_exception
An exception was thrown.
@ exception
An exception was thrown.
@ std_bad_alloc
A bad allocation exception was thrown.
@ allocerr
An error occurred during memory allocation.
@ paramnotset
A parameter was not set.
@ invalidconfig
A config setting was invalid.
@ invalidarg
An argument was invalid.
error_t mxlib_error_report(const error_t &code, const std::string &expl, const std::source_location &loc=std::source_location::current())
Print a report to stderr given an mxlib error_t code and explanation and return the code.
#define mxlib_error_check(fxn)
Perform an error check, if an error occurs report it and return the error. Does not return on no erro...
#define mxlib_error_return(fxn)
Perform an error check, if an error occurs report it, and return the error code even if no error.
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.
constexpr int fitsType()
Return the cfitsio constant for a given data type.
constexpr int fitsBITPIX()
static constexpr error_t fits_status2error_t(const int &err)
Convert a FITS status code to error_t.
Declarations of some libarary wide utilities.
Function object to return the number of planes for any Eigen like object, whether 2D or a 3D cube.