mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
fitsFile.hpp
Go to the documentation of this file.
1/** \file fitsFile.hpp
2 * \brief Declares and defines a class to work with a FITS file
3 * \ingroup fits_processing_files
4 * \author Jared R. Males (jaredmales@gmail.com)
5 *
6 */
7
8//***********************************************************************//
9// Copyright 2015-2022 Jared R. Males (jaredmales@gmail.com)
10//
11// This file is part of mxlib.
12//
13// mxlib is free software: you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation, either version 3 of the License, or
16// (at your option) any later version.
17//
18// mxlib is distributed in the hope that it will be useful,
19// but WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU General Public License for more details.
22//
23// You should have received a copy of the GNU General Public License
24// along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25//***********************************************************************//
26
27#ifndef ioutils_fits_fitsFile_hpp
28#define ioutils_fits_fitsFile_hpp
29
30#include <memory>
31
32#include "../../mxlib.hpp"
33
35
36#include "fitsUtils.hpp"
37#include "fitsHeader.hpp"
38
39namespace mx
40{
41namespace fits
42{
43
44namespace fitsFileDetail
45{
46
47/** \cond */
48/// Resettable CFITSIO operation table used by fitsFile and its deterministic failure tests.
49struct fitsFileCfitsioOps
50{
51 int ( *openFile )( fitsfile **, const char *, int, int * ); ///< Open an existing FITS file.
52 decltype( &ffgidm ) getImageDim; ///< Read the number of image axes.
53 decltype( &ffgisz ) getImageSize; ///< Read image-axis sizes.
54 decltype( &ffclos ) closeFile; ///< Close a FITS file.
55 decltype( &ffgsv ) readSubset; ///< Read a FITS pixel subset.
56 decltype( &ffghsp ) getHeaderSpace; ///< Read the number of FITS header cards.
57 decltype( &ffgkyn ) readKey; ///< Read one FITS header card.
58 decltype( &ffinit ) createFile; ///< Create a FITS file.
59 decltype( &ffcrim ) createImage; ///< Create the primary FITS image.
60 decltype( &ffppx ) writePixels; ///< Write FITS pixels.
61 long *( *allocateLongs )( size_t ); ///< Allocate a pixel-coordinate array.
62};
63
64/// Access the process-wide CFITSIO operation table.
65fitsFileCfitsioOps &fitsFileCfitsioOpsInstance();
66
67/// Restore every CFITSIO operation to its production implementation.
68void resetFitsFileCfitsioOps();
69/** \endcond */
70
71} // namespace fitsFileDetail
72
73/// Class to manage interactions with a FITS file
74/** This class wraps the functionality of cfitsio.
75 *
76 * \tparam dataT is the datatype to use for in-memory storage of the image.
77 * This does not have to match the data type
78 * stored on disk for reading, but will be the type used for writing.
79 *
80 * \ingroup fits_processing
81 */
82template <typename dataT, class verboseT = verbose::d>
84{
85
86 friend class fitsFile_test;
87
88 public:
89 typedef typename fitsHeader<verboseT>::headerIteratorT headerIteratorT;
90
91 protected:
92 /// The path to the file
93 std::string m_fileName;
94
95 /// The cfitsio data structure
96 fitsfile *m_fptr{ nullptr };
97
98 /// The dimensions of the image (1D, 2D, or 3D)
99 int m_naxis{ 0 };
100
101 /// The size of each dimension
102 long m_naxes[3];
103
104 /// Flag indicating whether the file is open or not
105 bool m_isOpen{ false };
106
107 /// The value to replace null values with
108 dataT m_nulval{ 0 };
109
110 /// Records whether any null values were replaced
111 int m_anynul{ 0 };
112
113 /// Flag to control whether the comment string is read.
114 int m_noComment{ 0 };
115
116 /// The starting x-pixel to read from
117 long m_x0{ -1 };
118
119 /// The starting y-pixel to read from
120 long m_y0{ -1 };
121
122 /// The number of x-pixels to read
123 long m_xpix{ -1 };
124
125 /// The number of y-pixels to read
126 long m_ypix{ -1 };
127
128 /// The starting frame to read from a cube
129 long m_z0{ -1 };
130
131 /// The number of frames to read from a cube
132 long m_zframes{ -1 };
133
134 /// One time initialization common to all constructors
135 void construct();
136
137 public:
138 /// Default constructor
140
141 /// Default constructor with error code
142 fitsFile( error_t &errc /**< [out] error_t code indicating success or error */ );
143
144 /// Constructor with file name and error code
145 /** The file is not opened.
146 *
147 */
148 fitsFile( const std::string &fname, ///< [in] File name to set on construction
149 error_t &errc /**< [out] error_t code indicating success or error */
150 );
151
152 /// Constructor with file name, and option to open.
153 fitsFile( const std::string &fname, ///< [in] File name to set on construction
154 bool doopen = true ///< [in] [optional] If true, then the file is opened (the default).
155 );
156
157 /// Constructor with file name, option to open, and error code
158 fitsFile( const std::string &fname, ///< File name to set on construction
159 bool doopen, ///< If true, then the file is opened (the default).
160 error_t &errc /**< [out] error_t code indicating success or error */
161 );
162
163 /// Destructor
165
166 /// Get the current value of m_fileName
167 /**
168 * \returns the current value of m_fileName.
169 */
170 std::string fileName();
171
172 /// Set the file path, and optionally open the file.
173 /**
174 * \returns mx::error_t::noerror on success
175 * \returns mx::error_t codes from \ref close or \ref open
176 */
177 error_t fileName( const std::string &fname, ///< The new file name.
178 bool doopen = true ///< If true, then the file is opened (the default).
179 );
180
181 /// Get the current value of m_naxis
182 /**
183 * \returns the current value of m_naxis
184 *
185 */
186 int naxis();
187
188 /// Get the current value of m_naxes for the specified dimension
189 /**
190 * \returns the current value of m_naxes for the specified dimension. -1 if no such dimension
191 *
192 */
193 long naxes( int dim /**< [in] the dimension */ );
194
195 /// Open the file and gets its dimensions.
196 /** File name needs to already have been set.
197 * If the file has already been opened, this returns immediately with no re-open.
198 *
199 * \returns mx::error_t::noerror on success
200 * \returns mx::invalidconfig if m_filename is empty.
201 * \returns mx::error_t::bad_alloc on an allocation error
202 * \returns mx::error_t::std_exception on other errors during allocations
203 * \returns mx::error_t::exception on unexpected errors during allocations
204 * \returns mx::error_t::allocerr if allocation fails without an exception
205 * \returns mx::error_t::fits_* codes from cfitsio functions
206 *
207 */
209
210 /// Open the file, first setting the file path.
211 /**
212 * \returns mx::error_t::noerror on success
213 * \returns mx::invalidconfig if m_filename is empty.
214 * \returns mx::error_t::bad_alloc on an allocation error
215 * \returns mx::error_t::std_exception on other errors during allocations
216 * \returns mx::error_t::exception on unexpected errors during allocations
217 * \returns mx::error_t::allocerr if allocation fails without an exception
218 * \returns mx::error_t::fits_* codes from cfitsio functions
219 */
220 error_t open( const std::string &fname /**< The name of the file to open. */ );
221
222 /// Close the file.
223 /**
224 * \returns mx::error_t::noerror on success
225 * \returns mx::error_t::fits_* codes from cfitsio functions
226 */
228
229 /// Get the number of dimensions (i.e. m_naxis)
230 int getDimensions( error_t &errc );
231
232 /// Get the total size
233 long getSize( error_t &errc );
234
235 /// Get the size of a specific dimension
236 long getSize( size_t axis, error_t &errc );
237
238 /** \name Reading Basic Arrays
239 * These methods read FITS data into basic or raw arrays specified by a pointer.
240 * @{
241 */
242
243 protected:
244 struct pixarrT
245 {
246 long *fpix{ nullptr }; ///< Populated with the lower left pixel to read.
247 long *lpix{ nullptr }; ///< Populated with the upper right pixel to read.
248 long *inc{ nullptr }; ///< The increment.
249
250 error_t allocate( int naxis )
251 {
252 if( naxis <= 0 )
253 {
255 }
256
257 if( fpix )
258 {
259 delete[] fpix;
260 fpix = nullptr;
261 }
262
263 if( lpix )
264 {
265 delete[] lpix;
266 lpix = nullptr;
267 }
268
269 if( inc )
270 {
271 delete[] inc;
272 inc = nullptr;
273 }
274
275 try
276 {
277 fpix = fitsFileDetail::fitsFileCfitsioOpsInstance().allocateLongs( naxis );
278 lpix = fitsFileDetail::fitsFileCfitsioOpsInstance().allocateLongs( naxis );
279 inc = fitsFileDetail::fitsFileCfitsioOpsInstance().allocateLongs( naxis );
280 }
281 catch( const std::bad_alloc &e )
282 {
284 std::string( "allocating pixel read arrays: " ) + e.what() );
285#ifdef MXLIB_TRAP_ALLOC_ERRORS
287#else
288 throw;
289#endif
290 }
291 catch( const std::exception &e )
292 {
294 std::string( "allocating pixel read arrays: " ) + e.what() );
295#ifdef MXLIB_TRAP_ALLOC_ERRORS
296 return error_t::exception;
297#else
298 throw;
299#endif
300 }
301 catch( ... )
302 {
303 internal::mxlib_error_report<verboseT>( error_t::exception, "allocating pixel read arrays" );
304#ifdef MXLIB_TRAP_ALLOC_ERRORS
305 return error_t::exception;
306#else
307 throw;
308#endif
309 }
310
311 // also check for null allocations (in case compiled with exceptions off)
312 if( fpix == nullptr )
313 {
315 }
316
317 if( lpix == nullptr )
318 {
320 }
321
322 if( inc == nullptr )
323 {
325 }
326
327 return error_t::noerror;
328 }
329
330 ~pixarrT()
331 {
332 if( fpix )
333 {
334 delete[] fpix;
335 }
336
337 if( lpix )
338 {
339 delete[] lpix;
340 }
341
342 if( inc )
343 {
344 delete[] inc;
345 }
346 }
347 };
348
349 /// Fill in the read-size arrays for reading a subset (always used)
350 /**
351 */
352 error_t calcPixarrs( pixarrT &pixarr /**< [out] Populated with the allocated read-size arrays*/ );
353
354 public:
355 /// Read the contents of the FITS file into an array.
356 /** The array pointed to by data must have been allocated.
357 *
358 * \returns 0 on success
359 * \returns -1 on error
360 */
361 error_t read( dataT *data /**< [out] an allocated arrray large enough to hold the entire image */ );
362
363 /// Read the contents of the FITS file into an array.
364 /** The array pointed to by data must have been allocated.
365 *
366 * \returns 0 on success
367 * \returns -1 on error
368 */
369 error_t read( dataT *data, ///< [out] an allocated arrray large enough to hold the entire image
370 fitsHeader<verboseT> &head ///< [out] a fitsHeader object which is passed to \ref readHeader
371 );
372
373 /// Read the contents of the FITS file into an array.
374 /** The array pointed to by data must have been allocated.
375 *
376 * \returns 0 on success
377 * \returns -1 on error
378 */
379 error_t read( dataT *data, ///< [out] is an allocated arrray large enough to hold the entire image
380 const std::string &fname ///< [in] is the file path, which is passed to \ref fileName
381 );
382
383 /// Read the contents of the FITS file into an array and read the header.
384 /** The array pointed to by data must have been allocated.
385 *
386 * \returns 0 on success
387 * \returns -1 on error
388 */
389 error_t read( dataT *data, ///< [out] an allocated arrray large enough to hold the entire image
390 fitsHeader<verboseT> &head, ///< [out] a fitsHeader object which is passed to \ref readHeader
391 const std::string &fname ///< [in] the file path, which is passed to \ref fileName
392 );
393
394 /// Read data from a vector list of files into an image cube
395 error_t read( dataT *im, ///< [out] An allocated array large enough to hold all the images
396 const std::vector<std::string> &flist ///< [in] The list of files to read.
397 );
398
399 /// Read data from a vector of files into an image cube with individual headers
400 error_t read( dataT *im, /**< [out] An allocated array large enough to hold all the images */
401 std::vector<fitsHeader<verboseT>> &heads, /**< [in/out] The vector of fits headers, allocated
402 to contain one per image. */
403 const std::vector<std::string> &flist /**< [in] The list of files to read. */
404 );
405
406 ///@}
407
408 /** \name Reading Eigen Arrays
409 * These methods read FITS data into array types with an Eigen-like interface.
410 * @{
411 */
412
413 /// Read the contents of the FITS file into an Eigen array type (not a simple pointer).
414 /** The type arrT can be any type with the following members defined:
415 * - resize(int, int) (allocates memory)
416 * - data() (returns a pointer to the underlying array)
417 * - typedef arrT::Scalar (is the data type, does not have to be dataT)
418 *
419 * \tparam arrT is the type of array, see requirements above.
420 *
421 * \returns 0 on success
422 * \returns -1 on error
423 */
424 template <typename arrT>
425 error_t read( arrT &data /**< [out] is the array, which will be resized as
426 necessary using its resize(int, int) member */ );
427
428 /// Read the contents of the FITS file into an Eigen array type (not a simple pointer).
429 /** The type arrT can be any type with the following members defined:
430 * - resize(int, int) (allocates memory)
431 * - data() (returns a pointer to the underlying array)
432 * - typedef arrT::Scalar (is the data type, does not have to be dataT)
433 *
434 * \tparam arrT is the type of array, see requirements above.
435 *
436 * \returns 0 on success
437 * \returns -1 on error
438 */
439 template <typename arrT>
440 error_t read( arrT &data, /**< [out] is the array, which will be resized as necessary
441 using its resize(int, int) member*/
442 fitsHeader<verboseT> &head ///< [out] is a fitsHeader object which is passed to \ref readHeader
443 );
444
445 /// Read the contents of the FITS file into an Eigen array type (not a simple pointer).
446 /** The type arrT can be any type with the following members defined:
447 * - resize(int, int) (allocates memory)
448 * - data() (returns a pointer to the underlying array)
449 * - typedef arrT::Scalar (is the data type, does not have to be dataT)
450 *
451 * \tparam arrT is the type of array, see requirements above.
452 *
453 * \returns 0 on success
454 * \returns -1 on error
455 */
456 template <typename arrT>
457 error_t read( arrT &data, /**< [out] is the array, which will be resized as
458 necessary using its resize(int, int) member*/
459 const std::string &fname ///< [in] is the file path, which is passed to \ref fileName
460 );
461
462 /// Read the contents of the FITS file into an Eigen array type (not a simple pointer).
463 /** The type arrT can be any type with the following members defined:
464 * - resize(int, int) (allocates memory)
465 * - data() (returns a pointer to the underlying array)
466 * - typedef arrT::Scalar (is the data type, does not have to be dataT)
467 *
468 * \tparam arrT is the type of array, see requirements above.
469 *
470 * \returns 0 on success
471 * \returns -1 on error
472 */
473 template <typename arrT>
474 error_t read( arrT &data, /**< [out] the array, which will be resized as
475 necessary using its resize(int, int) member*/
476 fitsHeader<verboseT> &head, ///< [out] a fitsHeader object which is passed to \ref readHeader
477 const std::string &fname ///< [in] the file path, which is passed to \ref fileName
478 );
479
480 /// Read data from a vector list of files into an image cube
481 /** The type cubeT can be any type with the following members defined:
482 * - resize(int, int, int) (allocates memory)
483 * - data() (returns a pointer to the underlying array)
484 * - typedef cubeT::Scalar (is the data type, does not have to be dataT)
485 *
486 * \note The images must all be the same size, or all be as large or larger than the subset specified.
487 *
488 * \tparam cubeT is the type of array, see requirements above.
489 *
490 * \returns 0 on success
491 * \returns -1 on error
492 */
493 template <typename cubeT>
494 error_t read( cubeT &cube, ///< [out] A cube which will be resized using its resize(int, int, int) member.
495 const std::vector<std::string> &flist, ///< [in] The list of files to read.
496 std::vector<fitsHeader<verboseT>> *heads =
497 0 ///< [out] [optional] A vector of fits headers, allocated to contain one per image.
498 );
499
500 /// Read data from a vector of files into an image cube with individual headers
501 /** The type cubeT can be any type with the following members defined:
502 * - resize(int, int, int) (allocates memory)
503 * - data() (returns a pointer to the underlying array)
504 * - typedef cubeT::Scalar (is the data type, does not have to be dataT)
505 *
506 * \tparam cubeT is the type of array, see requirements above.
507 *
508 * \returns 0 on success
509 * \returns -1 on error
510 */
511 template <typename cubeT>
512 error_t read( cubeT &cube, /**< [out] A cube which will be resized
513 using its resize(int, int, int) member.*/
514 std::vector<fitsHeader<verboseT>> &heads, /**< [out] The vector of fits headers, allocated to
515 contain one per image.*/
516 const std::vector<std::string> &flist ///< [in] The list of files to read.
517 );
518
519 ///@}
520
521 /** \name Reading Headers
522 * @{
523 */
524
525 /// Read the header from the fits file.
526 /** If head is not empty, then only the keywords already in head are updated. Otherwise
527 * the complete header is read.
528 *
529 * \returns 0 on success
530 * \returns -1 on error
531 */
532 error_t readHeader( fitsHeader<verboseT> &head /**< [out] a fitsHeader object */ );
533
534 /// Read the header from the fits file.
535 /** If head is not empty, then only the keywords already in head are updated. Otherwise
536 * the complete header is read.
537 *
538 * \returns 0 on success
539 * \returns -1 on error
540 */
541 error_t readHeader( fitsHeader<verboseT> &head, ///< [out] a fitsHeader object
542 const std::string &fname ///< [in] the file path, which is passed to \ref fileName
543 );
544
545 /// Read the headers from a list of FITS files.
546 /** In each case, if the header is not empty then only the keywords already in head are updated. Otherwise
547 * the complete header is read.
548 *
549 * \returns 0 on success
550 * \returns -1 on error
551 */
553 std::vector<fitsHeader<verboseT>> &heads, /// A vector of fitsHeader objects to read into.
554 const std::vector<std::string> &flist ///< [in] A list of files, each of which is passed to \ref fileName
555 );
556
557 ///@}
558
559 /** \name Writing Basic Arrays
560 * These methods write basic arrays specified by a pointer to FITS.
561 * @{
562 */
563
564 /// Write the contents of a raw array to the FITS file.
565 /**
566 * \returns 0 on success
567 * \returns -1 on error
568 */
569 error_t write( const dataT *im, ///< [in] is the array
570 int d1, ///< [in] is the first dimension
571 int d2, ///< [in] is the second dimension
572 int d3, ///< [in] is the third dimenesion (minimum value is 1)
573 fitsHeader<verboseT> *head ///< [in] a pointer to the header. Set to 0 if not used.
574 );
575
576 /// Write the contents of a raw array to the FITS file.
577 /**
578 * \returns 0 on success
579 * \returns -1 on error
580 */
581 error_t write( const dataT *im, ///< [in] is the array
582 int d1, ///< [in] is the first dimension
583 int d2, ///< [in] is the second dimension
584 int d3 ///< [in] is the third dimenesion (minimum value is 1)
585 );
586
587 /// Write the contents of a raw array to the FITS file.
588 /**
589 * Note: the type of the array must match dataT
590 *
591 * \returns 0 on success
592 * \returns -1 on error
593 */
594 error_t write( const dataT *im, ///< [in] is the array
595 int d1, ///< [in] is the first dimension
596 int d2, ///< [in] is the second dimension
597 int d3, ///< [in] is the third dimenesion (minimum value is 1)
598 fitsHeader<verboseT> &head ///< [in] is the header
599 );
600
601 /// Write the contents of a raw array to the FITS file.
602 /**
603 * \returns 0 on success
604 * \returns -1 on error
605 */
606 error_t write( const std::string &fname, ///< [in] is the name of the file.
607 const dataT *im, ///< [in] is the array
608 int d1, ///< [in] is the first dimension
609 int d2, ///< [in] is the second dimension
610 int d3 ///< [in] is the third dimenesion (minimum value is 1)
611 );
612
613 /// Write the contents of a raw array to the FITS file.
614 /**
615 * \returns 0 on success
616 * \returns -1 on error
617 */
618 error_t write( const std::string &fname, ///< [in] is the name of the file.
619 const dataT *im, ///< [in] is the array
620 int d1, ///< [in] is the first dimension
621 int d2, ///< [in] is the second dimension
622 int d3, ///< [in] is the third dimenesion (minimum value is 1)
623 fitsHeader<verboseT> &head ///< [in] is the header
624 );
625
626 ///@}
627
628 /** \name Writing Eigen Arrays
629 * These methods write array types with an Eigen-like interface.
630 * @{
631 */
632
633 /// Write the contents of an Eigen-type array to a FITS file.
634 /** The type arrT can be any type with the following members defined:
635 * - data() (returns a pointer to the underlying array)
636 * - rows() (returrns the number of rows)
637 * - cols() (returns the number of columns)
638 * - may have planes() defined
639 *
640 * Note: as with all write methods, the Scalar type of the array must match dataT
641 *
642 * \tparam arrT is the type of array, see requirements above.
643 *
644 * \returns 0 on success
645 * \returns -1 on error
646 */
647 template <typename arrT>
648 error_t write( const std::string &fname, ///< [in] is the name of the file.
649 const arrT &im ///< [in] is the array
650 );
651
652 /// Write the contents of an Eigen-type array to a FITS file.
653 /** The type arrT can be any type with the following members defined:
654 * - data() (returns a pointer to the underlying array)
655 * - rows() (returrns the number of rows)
656 * - cols() (returns the number of columns)
657 * - may have planes() defined.
658 *
659 * Note: as with all write methods, the Scalar type of the array must match dataT
660 *
661 * \tparam arrT is the type of array, see requirements above.
662 *
663 * \returns 0 on success
664 * \returns -1 on error
665 */
666 template <typename arrT>
667 error_t write( const std::string &fname, ///< [in] is the file path, which is passed to \ref fileName
668 const arrT &im, ///< [in] is the array
669 fitsHeader<verboseT> &head ///< [in] is a fitsHeader object which is passed to \ref readHeader
670 );
671
672 // int writeHeader( fitsHeader<verboseT> &head );
673
674 ///@}
675
676 /** \name Reading Subsets
677 * It is often desirable to read only a subset of an image or images into memory. These methods
678 * allow you to specify this.
679 * @{
680 */
681
682 /// Set to read all the pixels in the file
684
685 /// Set to read only a subset of the pixels in the file
686 /**
687 */
688 void setReadSize( long x0, ///< is the starting x-pixel to read
689 long y0, ///< is the starting y-pixel to read
690 long xpix, ///< is the number of x-pixels to read
691 long ypix ///< is the number of y-pixels to read
692 );
693
694 /// Set to read all frames from a cube.
695 /**
696 */
698
699 /// Set the number of frames to read from a cube.
700 /**
701 *
702 */
703 void setCubeReadSize( long z0, ///< is the starting frame to read
704 long zframes ///< is the number of frames to read
705 );
706
707 ///@}
708
709}; // fitsFile
710
711template <typename dataT, class verboseT>
715
716template <typename dataT, class verboseT>
721
722template <typename dataT, class verboseT>
723fitsFile<dataT, verboseT>::fitsFile( const std::string &fname, error_t &errc )
724{
725 // no errors are actually possible
726 errc = internal::mxlib_error_report<verboseT>( fileName( fname, false ) ); // nothing printed if noerror
727}
728
729template <typename dataT, class verboseT>
730fitsFile<dataT, verboseT>::fitsFile( const std::string &fname, bool doopen )
731{
732 // If an error happens on open(), then m_open will be false and this will persist
733 // so no need to throw an exception
734 internal::mxlib_error_report<verboseT>( fileName( fname, doopen ) ); // nothing printed if noerror
735}
736
737template <typename dataT, class verboseT>
738fitsFile<dataT, verboseT>::fitsFile( const std::string &fname, bool doopen, error_t &errc )
739{
740 // If an error happens on open(), then m_open will be false and this will persist
741 // so no need to throw an exception
742 errc = internal::mxlib_error_report<verboseT>( fileName( fname, doopen ) ); // nothing printed if noerror
743}
744
745template <typename dataT, class verboseT>
753
754template <typename dataT, class verboseT>
756{
757 return m_fileName;
758}
759
760template <typename dataT, class verboseT>
761error_t fitsFile<dataT, verboseT>::fileName( const std::string &fname, bool doopen )
762{
763 if( m_isOpen )
764 {
766 }
767
768 m_fileName = fname;
769
770 if( doopen )
771 {
773 }
774
775 return error_t::noerror;
776}
777
778template <typename dataT, class verboseT>
780{
781 return m_naxis;
782}
783
784template <typename dataT, class verboseT>
786{
787 if( dim >= m_naxis || dim > 2 )
788 {
789 return -1;
790 }
791
792 return m_naxes[dim];
793}
794
795template <typename dataT, class verboseT>
797{
798 if( m_isOpen ) // no-op
799 {
800 return error_t::noerror;
801 }
802
803 if( m_fileName == "" )
804 {
805 return internal::mxlib_error_report<verboseT>( error_t::invalidconfig, "File name is not set" );
806 }
807
808 int fstatus = 0;
809
810 fitsFileDetail::fitsFileCfitsioOpsInstance().openFile( &m_fptr, m_fileName.c_str(), READONLY, &fstatus );
811
812 if( fstatus )
813 {
814 return internal::mxlib_error_report<verboseT>( fits_status2error_t( fstatus ), "Opening file " + m_fileName );
815 }
816
817 fstatus = 0;
818 fitsFileDetail::fitsFileCfitsioOpsInstance().getImageDim( m_fptr, &m_naxis, &fstatus );
819 if( fstatus )
820 {
821 int closeStatus = 0;
822 ffclos( m_fptr, &closeStatus );
823 m_fptr = nullptr;
825 "Getting number of axes in file " + m_fileName );
826 }
827
828 fstatus = 0;
829 fitsFileDetail::fitsFileCfitsioOpsInstance().getImageSize( m_fptr, m_naxis, m_naxes, &fstatus );
830 if( fstatus )
831 {
832 int closeStatus = 0;
833 ffclos( m_fptr, &closeStatus );
834 m_fptr = nullptr;
836 "Getting dimensions in file " + m_fileName );
837 }
838
839 m_isOpen = true; // Only set this after opening is complete.
840
841 return error_t::noerror;
842}
843
844template <typename dataT, class verboseT>
845error_t fitsFile<dataT, verboseT>::open( const std::string &fname )
846{
847 mxlib_error_return( fileName( fname, true ) );
848}
849
850template <typename dataT, class verboseT>
852{
853 if( !m_isOpen )
854 {
855 return error_t::noerror; // No error.
856 }
857
858 int fstatus = 0;
859 fitsFileDetail::fitsFileCfitsioOpsInstance().closeFile( m_fptr, &fstatus );
860
861 if( fstatus )
862 {
863 return internal::mxlib_error_report<verboseT>( fits_status2error_t( fstatus ), "Closing file " + m_fileName );
864 }
865
866 m_fptr = nullptr;
867 m_isOpen = false;
868
869 return error_t::noerror;
870}
871
872template <typename dataT, class verboseT>
874{
875 if( !m_isOpen )
876 {
878 return -1;
879 }
880
881 return m_naxis;
882}
883
884template <typename dataT, class verboseT>
886{
887 if( !m_isOpen )
888 {
890 return -1;
891 }
892
893 long sz = 1;
894
895 errc = error_t::noerror;
896
897 if( m_naxis == 1 )
898 {
899 if( m_x0 > -1 && m_xpix > -1 )
900 {
901 return m_xpix;
902 }
903 return m_naxes[0];
904 }
905 else if( m_x0 > -1 && m_y0 > -1 && m_xpix > -1 && m_ypix > -1 && m_naxis == 2 )
906 {
907 return m_xpix * m_ypix;
908 }
909 else
910 {
911 for( int i = 0; i < m_naxis && i < 3; ++i )
912 {
913 sz *= m_naxes[i];
914 }
915 }
916
917 return sz;
918}
919
920template <typename dataT, class verboseT>
922{
923 if( !m_isOpen )
924 {
926 return -1;
927 }
928
929 if( axis >= m_naxis || axis > 2 )
930 {
931 errc = error_t::invalidarg;
932 return -1;
933 }
934
935 errc = error_t::noerror;
936
937 if( m_naxis == 1 && m_x0 > -1 && m_xpix > -1 )
938 {
939 return m_xpix;
940 }
941 else if( m_x0 > -1 && m_y0 > -1 && m_xpix > -1 && m_ypix > -1 && m_naxis == 2 )
942 {
943 if( axis == 0 )
944 {
945 return m_xpix;
946 }
947 return m_ypix;
948 }
949 else
950 {
951 return m_naxes[axis];
952 }
953}
954
955template <typename dataT, class verboseT>
957{
958 error_t errc = pixarr.allocate( m_naxis );
959 if( errc != error_t::noerror )
960 {
962 }
963
964 if( m_naxis == 1 )
965 {
966 if( m_x0 > -1 && m_xpix > -1 )
967 {
968 pixarr.fpix[0] = m_x0 + 1;
969 pixarr.lpix[0] = pixarr.fpix[0] + m_xpix - 1;
970 }
971 else
972 {
973 pixarr.fpix[0] = 1;
974 pixarr.lpix[0] = m_naxes[0];
975 }
976 pixarr.inc[0] = 1;
977 }
978 else if( m_x0 > -1 && m_y0 > -1 && m_xpix > -1 && m_ypix > -1 && m_naxis == 2 )
979 {
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;
984
985 pixarr.inc[0] = 1;
986 pixarr.inc[1] = 1;
987 }
988 else
989 {
990 if( m_x0 < 0 && m_y0 < 0 && m_xpix < 0 && m_ypix < 0 && m_z0 < 0 && m_zframes < 0 )
991 {
992 for( int i = 0; i < m_naxis && i < 3; i++ )
993 {
994 pixarr.fpix[i] = 1;
995 pixarr.lpix[i] = m_naxes[i];
996 pixarr.inc[i] = 1;
997 }
998 }
999 else
1000 {
1001 if( m_x0 > -1 && m_y0 > -1 && m_xpix > -1 && m_ypix > -1 )
1002 {
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;
1007
1008 pixarr.inc[0] = 1;
1009 pixarr.inc[1] = 1;
1010 }
1011 else
1012 {
1013 pixarr.fpix[0] = 1;
1014 pixarr.lpix[0] = m_naxes[0];
1015 pixarr.fpix[1] = 1;
1016 pixarr.lpix[1] = m_naxes[1];
1017
1018 pixarr.inc[0] = 1;
1019 pixarr.inc[1] = 1;
1020 }
1021
1022 if( m_z0 > -1 && m_zframes > -1 )
1023 {
1024 pixarr.fpix[2] = m_z0 + 1;
1025 pixarr.lpix[2] = pixarr.fpix[2] + m_zframes - 1;
1026 pixarr.inc[2] = 1;
1027 }
1028 else
1029 {
1030 pixarr.fpix[2] = 1;
1031 pixarr.lpix[2] = m_naxes[2];
1032 pixarr.inc[2] = 1;
1033 }
1034 }
1035 }
1036
1037 return error_t::noerror;
1038}
1039
1040/************************************************************/
1041/*** Basic Arrays ***/
1042/************************************************************/
1043
1044template <typename dataT, class verboseT>
1046{
1047 if( !m_isOpen )
1048 {
1050 }
1051
1052 pixarrT pixarrs;
1053
1054 mxlib_error_check( calcPixarrs( pixarrs ) );
1055
1056 ///\todo test if there is a speed difference for full reads for fits_read_pix/subset
1057
1058 int fstatus = 0;
1059
1060 fitsFileDetail::fitsFileCfitsioOpsInstance().readSubset( m_fptr,
1062 pixarrs.fpix,
1063 pixarrs.lpix,
1064 pixarrs.inc,
1065 (void *)&m_nulval,
1066 (void *)data,
1067 &m_anynul,
1068 &fstatus );
1069
1070 if( fstatus && fstatus != END_OF_FILE )
1071 {
1073 "Reading data from " + m_fileName );
1074 }
1075
1076 return error_t::noerror;
1077}
1078
1079template <typename dataT, class verboseT>
1081{
1082 mxlib_error_check( read( data ) );
1083
1084 mxlib_error_return( readHeader( head ) );
1085}
1086
1087template <typename dataT, class verboseT>
1088error_t fitsFile<dataT, verboseT>::read( dataT *data, const std::string &fname )
1089{
1090 mxlib_error_check( fileName( fname ) );
1091
1092 mxlib_error_return( read( data ) );
1093}
1094
1095template <typename dataT, class verboseT>
1096error_t fitsFile<dataT, verboseT>::read( dataT *data, fitsHeader<verboseT> &head, const std::string &fname )
1097{
1098 mxlib_error_check( fileName( fname ) );
1099
1100 mxlib_error_check( read( data ) );
1101
1102 mxlib_error_return( readHeader( head ) );
1103}
1104
1105template <typename dataT, class verboseT>
1106error_t fitsFile<dataT, verboseT>::read( dataT *im, const std::vector<std::string> &flist )
1107{
1108 if( flist.size() == 0 )
1109 {
1111 }
1112
1113 long sz0 = 0, sz1 = 0;
1114
1115 for( int i = 0; i < flist.size(); ++i )
1116 {
1117 mxlib_error_check( fileName( flist[i], 1 ) );
1118
1119 mxlib_error_check( read( im + i * sz0 * sz1 ) );
1120
1121 error_t errc;
1122 sz0 = getSize( 0, errc );
1123 mxlib_error_check( errc );
1124
1125 sz1 = getSize( 1, errc );
1126 mxlib_error_check( errc );
1127 }
1128
1129 return error_t::noerror;
1130}
1131
1132template <typename dataT, class verboseT>
1134 std::vector<fitsHeader<verboseT>> &heads,
1135 const std::vector<std::string> &flist )
1136{
1137 if( flist.size() == 0 )
1138 {
1140 }
1141
1142 if( heads.size() != flist.size() )
1143 {
1145 "Header vector is not the same size as the file list" );
1146 }
1147
1148 long sz0 = 0, sz1 = 0;
1149
1150 for( size_t i = 0; i < flist.size(); ++i )
1151 {
1152
1153 mxlib_error_check( fileName( flist[i], 1 ) );
1154
1155 mxlib_error_check( read( im + i * sz0 * sz1 ) );
1156
1157 mxlib_error_check( readHeader( heads[i] ) );
1158
1159 error_t errc;
1160 sz0 = getSize( 0, errc );
1161 mxlib_error_check( errc );
1162
1163 sz1 = getSize( 1, errc );
1164 mxlib_error_check( errc );
1165 }
1166
1167 return error_t::noerror;
1168}
1169
1170/************************************************************/
1171/*** Eigen Arrays ***/
1172/************************************************************/
1173
1174template <typename arrT, class verboseT, bool isCube = improc::is_eigenCube<arrT>::value>
1175struct eigenArrResize
1176{
1177 // If it's a cube, always pass zsz
1178 error_t resize( arrT &arr, int xsz, int ysz, int zsz )
1179 {
1180 try
1181 {
1182 arr.resize( xsz, ysz, zsz );
1183 }
1184 catch( const std::bad_alloc &e )
1185 {
1187 std::string( "resizing array: " ) + e.what() );
1188#ifdef MXLIB_TRAP_ALLOC_ERRORS
1190#else
1191 throw;
1192#endif
1193 }
1194 catch( const std::exception &e )
1195 {
1197 std::string( "resizing array: " ) + e.what() );
1198#ifdef MXLIB_TRAP_ALLOC_ERRORS
1200#else
1201 throw;
1202#endif
1203 }
1204 catch( ... )
1205 {
1207#ifdef MXLIB_TRAP_ALLOC_ERRORS
1208 return error_t::exception;
1209#else
1210 throw;
1211#endif
1212 }
1213
1214 return error_t::noerror;
1215 }
1216};
1217
1218template <typename arrT, class verboseT>
1219struct eigenArrResize<arrT, verboseT, false>
1220{
1221 // If it's not a cube, never pass zsz
1222 error_t resize( arrT &arr, int xsz, int ysz, [[maybe_unused]] int zsz )
1223 {
1224 try
1225 {
1226 arr.resize( xsz, ysz );
1227 }
1228 catch( const std::bad_alloc &e )
1229 {
1231 std::string( "resizing array: " ) + e.what() );
1232#ifdef MXLIB_TRAP_ALLOC_ERRORS
1234#else
1235 throw;
1236#endif
1237 }
1238 catch( const std::exception &e )
1239 {
1241 std::string( "resizing array: " ) + e.what() );
1242#ifdef MXLIB_TRAP_ALLOC_ERRORS
1244#else
1245 throw;
1246#endif
1247 }
1248 catch( ... )
1249 {
1251#ifdef MXLIB_TRAP_ALLOC_ERRORS
1252 return error_t::exception;
1253#else
1254 throw;
1255#endif
1256 }
1257
1258 return error_t::noerror;
1259 }
1260};
1261
1262template <typename dataT, class verboseT>
1263template <typename arrT>
1265{
1266 ///\todo this can probably be made part of one read function (or call read(data *)) with a call to resize with
1267 /// SFINAE
1268 int fstatus = 0;
1269
1270 if( !m_isOpen )
1271 {
1273 }
1274
1275 pixarrT pixarrs;
1276 mxlib_error_check( calcPixarrs( pixarrs ) );
1277
1278 eigenArrResize<arrT, verboseT> arrresz;
1279 if( m_naxis > 2 )
1280 {
1281 mxlib_error_check( arrresz.resize( im,
1282 pixarrs.lpix[0] - pixarrs.fpix[0] + 1,
1283 pixarrs.lpix[1] - pixarrs.fpix[1] + 1,
1284 pixarrs.lpix[2] - pixarrs.fpix[2] + 1 ) );
1285 }
1286 else if( m_naxis > 1 )
1287 {
1289 arrresz.resize( im, pixarrs.lpix[0] - pixarrs.fpix[0] + 1, pixarrs.lpix[1] - pixarrs.fpix[1] + 1, 1 ) );
1290 }
1291 else
1292 {
1293 mxlib_error_check( arrresz.resize( im, pixarrs.lpix[0] - pixarrs.fpix[0] + 1, 1, 1 ) );
1294 }
1295
1296 fitsFileDetail::fitsFileCfitsioOpsInstance().readSubset( m_fptr,
1298 pixarrs.fpix,
1299 pixarrs.lpix,
1300 pixarrs.inc,
1301 (void *)&m_nulval,
1302 (void *)im.data(),
1303 &m_anynul,
1304 &fstatus );
1305
1306 if( fstatus && fstatus != END_OF_FILE )
1307 {
1309 "Reading data from " + m_fileName );
1310 }
1311
1312 return error_t::noerror;
1313}
1314
1315template <typename dataT, class verboseT>
1316template <typename arrT>
1318{
1319 error_t errc;
1320 errc = read( data );
1321 if( errc != error_t::noerror )
1322 {
1324 }
1325
1326 errc = readHeader( head );
1327 if( errc != error_t::noerror )
1328 {
1330 }
1331
1332 return error_t::noerror;
1333}
1334
1335template <typename dataT, class verboseT>
1336template <typename arrT>
1337error_t fitsFile<dataT, verboseT>::read( arrT &data, const std::string &fname )
1338{
1339 error_t errc;
1340 errc = fileName( fname );
1341 if( errc != error_t::noerror )
1342 {
1344 }
1345
1346 errc = read( data );
1347 if( errc != error_t::noerror )
1348 {
1350 }
1351 return error_t::noerror;
1352}
1353
1354template <typename dataT, class verboseT>
1355template <typename arrT>
1356error_t fitsFile<dataT, verboseT>::read( arrT &data, fitsHeader<verboseT> &head, const std::string &fname )
1357{
1358 error_t errc;
1359 errc = fileName( fname );
1360 if( errc != error_t::noerror )
1361 {
1363 }
1364
1365 errc = read( data );
1366 if( errc != error_t::noerror )
1367 {
1369 }
1370
1371 errc = readHeader( head );
1372 if( errc != error_t::noerror )
1373 {
1375 }
1376
1377 return error_t::noerror;
1378}
1379
1380template <typename dataT, class verboseT>
1381template <typename cubeT>
1383 const std::vector<std::string> &flist,
1384 std::vector<fitsHeader<verboseT>> *heads )
1385{
1386 error_t errc;
1387 int fstatus = 0;
1388
1389 if( flist.size() == 0 )
1390 {
1392 }
1393
1394 if( heads && heads->size() != flist.size() )
1395 {
1397 "Header vector is not the same size as the file list" );
1398 }
1399
1400 // Open the first file to get the dimensions.
1401 errc = fileName( flist[0], 1 );
1402 if( !!errc )
1403 {
1405 }
1406
1407 pixarrT pixarrs;
1408 errc = calcPixarrs( pixarrs );
1409
1410 if( !!errc )
1411 {
1413 }
1414
1415 cube.resize( pixarrs.lpix[0] - pixarrs.fpix[0] + 1, pixarrs.lpix[1] - pixarrs.fpix[1] + 1, flist.size() );
1416
1417 // Now read first image.
1418 fitsFileDetail::fitsFileCfitsioOpsInstance().readSubset( m_fptr,
1420 pixarrs.fpix,
1421 pixarrs.lpix,
1422 pixarrs.inc,
1423 (void *)&m_nulval,
1424 (void *)cube.image( 0 ).data(),
1425 &m_anynul,
1426 &fstatus );
1427
1428 if( fstatus && fstatus != END_OF_FILE )
1429 {
1431 "Reading data from " + m_fileName );
1432 }
1433
1434 if( heads )
1435 {
1436 errc = readHeader( ( *heads )[0] );
1437 if( errc != error_t::noerror )
1438 {
1440 }
1441 }
1442
1443 // Now read in the rest.
1444 for( int i = 1; i < flist.size(); ++i )
1445 {
1446 errc = fileName( flist[i], 1 );
1447 if( errc != error_t::noerror )
1448 {
1450 }
1451
1452 // Now read image.
1453 fitsFileDetail::fitsFileCfitsioOpsInstance().readSubset( m_fptr,
1455 pixarrs.fpix,
1456 pixarrs.lpix,
1457 pixarrs.inc,
1458 (void *)&m_nulval,
1459 (void *)cube.image( i ).data(),
1460 &m_anynul,
1461 &fstatus );
1462
1463 if( fstatus && fstatus != END_OF_FILE )
1464 {
1466 "Reading data from " + m_fileName );
1467 }
1468
1469 if( heads )
1470 {
1471 errc = readHeader( ( *heads )[i] );
1472 if( errc != error_t::noerror )
1473 {
1475 }
1476 }
1477 }
1478
1479 return error_t::noerror;
1480}
1481
1482template <typename dataT, class verboseT>
1483template <typename cubeT>
1485 std::vector<fitsHeader<verboseT>> &heads,
1486 const std::vector<std::string> &flist )
1487{
1488 mxlib_error_return( read( cube, flist, &heads ) );
1489}
1490
1491template <typename dataT, class verboseT>
1493{
1494 int fstatus = 0;
1495
1496 char keyword[FLEN_KEYWORD];
1497 char value[FLEN_VALUE];
1498 std::unique_ptr<char[]> commentStorage;
1499 char *comment = nullptr;
1500
1501 // The keys to look for if head is already populated
1502 typename std::list<headerIteratorT> head_keys;
1503 typename std::list<headerIteratorT>::iterator head_keys_it;
1504 // int num_head_keys;
1505
1506 bool head_keys_only = false;
1507 if( head.size() > 0 )
1508 {
1509 head_keys_only = true;
1510 headerIteratorT headIt = head.begin();
1511 while( headIt != head.end() )
1512 {
1513 head_keys.push_back( headIt );
1514 ++headIt;
1515 }
1516 // num_head_keys = head.size();
1517 }
1518
1519 // If m_noComment is set, then we don't read in the comment
1520 if( m_noComment )
1521 {
1522 comment = nullptr;
1523 }
1524 else
1525 {
1526 commentStorage = std::make_unique<char[]>( FLEN_COMMENT );
1527 comment = commentStorage.get();
1528 }
1529
1530 int keysexist;
1531 int morekeys;
1532
1533 if( !m_isOpen )
1534 {
1536 }
1537
1538 // This gets the number of header keys to read
1539 fitsFileDetail::fitsFileCfitsioOpsInstance().getHeaderSpace( m_fptr, &keysexist, &morekeys, &fstatus );
1540
1541 if( fstatus )
1542 {
1544 "Reading header from " + m_fileName );
1545 }
1546
1547 for( int i = 0; i < keysexist; i++ )
1548 {
1549 fitsFileDetail::fitsFileCfitsioOpsInstance().readKey( m_fptr, i + 1, keyword, value, comment, &fstatus );
1550
1551 if( fstatus )
1552 {
1554 "Reading header from " + m_fileName );
1555 }
1556
1557 if( !head_keys_only )
1558 {
1559 if( strcmp( keyword, "COMMENT" ) == 0 )
1560 {
1561 head.template append<fitsCommentType>( keyword, fitsCommentType( value ), comment );
1562 }
1563 else if( strcmp( keyword, "HISTORY" ) == 0 )
1564 {
1565 head.template append<fitsHistoryType>( keyword, fitsHistoryType( value ), comment );
1566 }
1567 else
1568 {
1569 // Otherwise we append it as an unknown type
1570 head.append( keyword, value, comment );
1571 }
1572 }
1573 else
1574 {
1575 head_keys_it = head_keys.begin();
1576 while( head_keys_it != head_keys.end() )
1577 {
1578 if( ( *( *head_keys_it ) ).keyword() == keyword )
1579 {
1580 head[keyword].value( (const char *)value );
1581 if( comment )
1582 {
1583 head[keyword].comment( comment );
1584 }
1585
1586 head_keys.erase( head_keys_it );
1587
1588 break;
1589 }
1590 ++head_keys_it;
1591 }
1592
1593 // Quit if we're done.
1594 if( head_keys.empty() )
1595 {
1596 break;
1597 }
1598 }
1599 }
1600
1601 return error_t::noerror;
1602}
1603
1604template <typename dataT, class verboseT>
1606{
1607 error_t errc;
1608 mxlib_error_check( fileName( fname ) );
1609 mxlib_error_check( readHeader( head ) );
1610 return error_t::noerror;
1611}
1612
1613template <typename dataT, class verboseT>
1615 const std::vector<std::string> &flist )
1616{
1617 if( heads.size() != 0 && heads.size() != flist.size() )
1618 {
1620 "head vector is not empty and not same size as file list" );
1621 }
1622
1623 if( heads.size() == 0 )
1624 {
1625 heads.resize( flist.size() );
1626 }
1627
1628 error_t errc;
1629 for( int i = 0; i < flist.size(); ++i )
1630 {
1631 mxlib_error_check( fileName( flist[i], 1 ) );
1632
1633 mxlib_error_check( readHeader( heads[i] ) );
1634 }
1635
1636 return error_t::noerror;
1637}
1638
1639template <typename dataT, class verboseT>
1640error_t fitsFile<dataT, verboseT>::write( const dataT *im, int d1, int d2, int d3, fitsHeader<verboseT> *head )
1641{
1642 int fstatus = 0;
1643
1644 if( m_isOpen )
1645 {
1647 }
1648
1649 m_naxis = 1;
1650 if( d2 > 0 )
1651 {
1652 if( d3 > 1 )
1653 {
1654 m_naxis = 3;
1655 }
1656 else
1657 {
1658 m_naxis = 2;
1659 }
1660 }
1661
1662 m_naxes[0] = d1;
1663 if( m_naxis > 1 )
1664 {
1665 m_naxes[1] = d2;
1666 }
1667 if( m_naxis > 2 )
1668 {
1669 m_naxes[2] = d3;
1670 }
1671
1672 std::string forceFileName = "!" + m_fileName;
1673
1674 fitsFileDetail::fitsFileCfitsioOpsInstance().createFile( &m_fptr, forceFileName.c_str(), &fstatus );
1675 if( fstatus )
1676 {
1677 return internal::mxlib_error_report<verboseT>( fits_status2error_t( fstatus ), "Creating " + m_fileName );
1678 }
1679 m_isOpen = true;
1680
1681 fstatus = 0;
1682 fitsFileDetail::fitsFileCfitsioOpsInstance().createImage( m_fptr, fitsBITPIX<dataT>(), m_naxis, m_naxes, &fstatus );
1683 if( fstatus )
1684 {
1686 "Creating image in" + m_fileName );
1687 }
1688
1689 long fpixel[3];
1690 fpixel[0] = 1;
1691 fpixel[1] = 1;
1692 fpixel[2] = 1;
1693
1694 LONGLONG nelements = 1;
1695
1696 for( int i = 0; i < m_naxis && i < 3; ++i )
1697 {
1698 nelements *= m_naxes[i];
1699 }
1700
1701 fstatus = 0;
1702 fitsFileDetail::fitsFileCfitsioOpsInstance()
1703 .writePixels( m_fptr, fitsType<dataT>(), fpixel, nelements, (void *)im, &fstatus );
1704 if( fstatus )
1705 {
1706 return internal::mxlib_error_report<verboseT>( fits_status2error_t( fstatus ), "Writing data " + m_fileName );
1707 }
1708
1709 if( head != 0 )
1710 {
1711 headerIteratorT it;
1712
1713 for( it = head->begin(); it != head->end(); ++it )
1714 {
1715 error_t errc = it->write( m_fptr );
1716 if( errc != error_t::noerror )
1717 {
1718 return internal::mxlib_error_report<verboseT>( errc, "Writing keyword " + m_fileName );
1719 }
1720 }
1721 }
1722
1724}
1725
1726template <typename dataT, class verboseT>
1727error_t fitsFile<dataT, verboseT>::write( const dataT *im, int d1, int d2, int d3 )
1728{
1729 mxlib_error_return( write( im, d1, d2, d3, (fitsHeader<verboseT> *)0 ) );
1730}
1731
1732template <typename dataT, class verboseT>
1733error_t fitsFile<dataT, verboseT>::write( const dataT *im, int d1, int d2, int d3, fitsHeader<verboseT> &head )
1734{
1735 mxlib_error_return( write( im, d1, d2, d3, &head ) );
1736}
1737
1738template <typename dataT, class verboseT>
1739error_t fitsFile<dataT, verboseT>::write( const std::string &fname, const dataT *im, int d1, int d2, int d3 )
1740{
1741 mxlib_error_check( fileName( fname, false ) );
1742
1743 mxlib_error_return( write( im, d1, d2, d3, (fitsHeader<verboseT> *)0 ) );
1744}
1745
1746template <typename dataT, class verboseT>
1748 const std::string &fname, const dataT *im, int d1, int d2, int d3, fitsHeader<verboseT> &head )
1749{
1750 mxlib_error_check( fileName( fname, false ) );
1751
1752 mxlib_error_return( write( im, d1, d2, d3, &head ) );
1753}
1754
1755template <typename dataT, class verboseT>
1756template <typename arrT>
1757error_t fitsFile<dataT, verboseT>::write( const std::string &fname, const arrT &im )
1758{
1760
1761 mxlib_error_return( write( fname, im.data(), im.rows(), im.cols(), planes( im ) ) );
1762}
1763
1764template <typename dataT, class verboseT>
1765template <typename arrT>
1766error_t fitsFile<dataT, verboseT>::write( const std::string &fname, const arrT &im, fitsHeader<verboseT> &head )
1767{
1769
1770 return write( fname, im.data(), im.rows(), im.cols(), planes( im ), head );
1771}
1772
1773template <typename dataT, class verboseT>
1775{
1776 m_x0 = -1;
1777 m_y0 = -1;
1778 m_xpix = -1;
1779 m_ypix = -1;
1780}
1781
1782template <typename dataT, class verboseT>
1783void fitsFile<dataT, verboseT>::setReadSize( long x0, long y0, long xpix, long ypix )
1784{
1785 m_x0 = x0;
1786 m_y0 = y0;
1787 m_xpix = xpix;
1788 m_ypix = ypix;
1789}
1790
1791template <typename dataT, class verboseT>
1793{
1794 m_z0 = -1;
1795 m_zframes = -1;
1796}
1797
1798template <typename dataT, class verboseT>
1800{
1801 m_z0 = z0;
1802 m_zframes = zframes;
1803}
1804
1805/** \ingroup fits_processing_typedefs
1806 * @{
1807 */
1808
1809/// A \ref fitsFile to work in signed characters
1811
1812/// A \ref fitsFile to work in unsigned characters
1814
1815/// A \ref fitsFile to work in signed short integers
1817
1818/// A \ref fitsFile to work in unsigned short integers
1820
1821/// A \ref fitsFile to work in signed integers
1823
1824/// A \ref fitsFile to work in unsigned integers
1826
1827/// A \ref fitsFile to work in signed long integers
1829
1830/// A \ref fitsFile to work in single precision floats
1832
1833/// A \ref fitsFile to work in double precision
1835
1836///@}
1837
1838extern template class fitsFile<short, verbose::d>;
1839extern template class fitsFile<unsigned short, verbose::d>;
1840extern template class fitsFile<int, verbose::d>;
1841extern template class fitsFile<unsigned int, verbose::d>;
1842extern template class fitsFile<float, verbose::d>;
1843extern template class fitsFile<double, verbose::d>;
1844
1845} // namespace fits
1846} // namespace mx
1847
1848#endif // ioutils_fits_fitsFile_hpp
Class to manage interactions with a FITS file.
Definition fitsFile.hpp:84
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.
Definition fitsFile.hpp:779
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.
Definition fitsFile.hpp:723
error_t open(const std::string &fname)
Open the file, first setting the file path.
Definition fitsFile.hpp:845
long getSize(error_t &errc)
Get the total size.
Definition fitsFile.hpp:885
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.
Definition fitsFile.hpp:785
error_t open()
Open the file and gets its dimensions.
Definition fitsFile.hpp:796
std::string fileName()
Get the current value of m_fileName.
Definition fitsFile.hpp:755
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).
Definition fitsFile.hpp:873
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.
Definition fitsFile.hpp:712
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.
Definition fitsFile.hpp:717
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.
Definition fitsFile.hpp:730
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.
~fitsFile()
Destructor.
Definition fitsFile.hpp:746
error_t fileName(const std::string &fname, bool doopen=true)
Set the file path, and optionally open the file.
Definition fitsFile.hpp:761
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.
Definition fitsFile.hpp:851
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).
Definition fitsFile.hpp:956
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.
Definition fitsFile.hpp:738
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.
Definition fitsFile.hpp:921
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.
Class to manage a FITS file metadata header and provide fast access to the cards by keyword.
error_t append(const fitsHeaderCard< verboseT > &card)
Append a fitsHeaderCard to the end of the header.
cardListT::iterator headerIteratorT
The iterator type for the cards list.
error_t erase(const std::string &keyword)
Erase card by keyword.
size_t size()
Get number of cards currently stored in the header.
headerIteratorT end()
Get iterator to the end of the cards list.
headerIteratorT begin()
Get iterator to the beginning of the cards list.
Tools for using the eigen library for image processing.
Declares and defines a class to work with a FITS header.
Declares and defines utilities to work with FITS files.
error_t
The mxlib error codes.
Definition error_t.hpp:26
@ noerror
No error has occurred.
Definition error_t.hpp:27
@ std_exception
An exception was thrown.
Definition error_t.hpp:52
@ exception
An exception was thrown.
Definition error_t.hpp:51
@ std_bad_alloc
A bad allocation exception was thrown.
Definition error_t.hpp:53
@ allocerr
An error occurred during memory allocation.
Definition error_t.hpp:36
@ paramnotset
A parameter was not set.
Definition error_t.hpp:32
@ invalidconfig
A config setting was invalid.
Definition error_t.hpp:30
@ invalidarg
An argument was invalid.
Definition error_t.hpp:29
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.
Definition error.hpp:331
#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...
Definition error.hpp:405
#define mxlib_error_return(fxn)
Perform an error check, if an error occurs report it, and return the error code even if no error.
Definition error.hpp:424
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.
Definition error_t.hpp:2219
Declarations of some libarary wide utilities.
The mxlib c++ namespace.
Definition mxlib.hpp:37
Function object to return the number of planes for any Eigen like object, whether 2D or a 3D cube.