psrfitsio.h
1//-*-C++-*-
2/***************************************************************************
3 *
4 * Copyright (C) 2006 - 2025 by Willem van Straten
5 * Licensed under the Academic Free License version 2.1
6 *
7 ***************************************************************************/
8
9// psrchive/Util/fitsutil/psrfitsio.h
10
11#ifndef __psrfitsio_h
12#define __psrfitsio_h
13
14#include "FITSError.h"
15#include "ReferenceTo.h"
16#include "fitsutil.h"
17
18#include <fitsio.h>
19
20#include <string>
21#include <vector>
22#include <complex>
23
24extern bool psrfits_verbose;
25
27template<typename T> struct FITS_traits { };
28
30template<> struct FITS_traits<double>
31{
32 static inline int datatype() { return TDOUBLE; }
33 static inline double null () { return 0; }
34};
35
37template<> struct FITS_traits<float>
38{
39 static inline int datatype() { return TFLOAT; }
40 static inline float null () { return fits_nullfloat; }
41};
42
44template<> struct FITS_traits<short>
45{
46 static inline int datatype() { return TSHORT; }
47 static inline short null () { return -1; }
48};
49
51template<> struct FITS_traits<int>
52{
53 static inline int datatype() { return TINT; }
54 static inline int null () { return -1; }
55};
56
58template<> struct FITS_traits<long> {
59 static inline int datatype() { return TLONG; }
60 static inline long null () { return -1; }
61};
62
64template<> struct FITS_traits<long long> {
65 static inline int datatype() { return TLONGLONG; }
66 static inline long null () { return -1; }
67};
68
70template<> struct FITS_traits<unsigned> {
71 static inline int datatype() { return TUINT; }
72 static inline long null () { return 0; }
73};
74
76template<> struct FITS_traits<std::string>
77{
78 static inline int datatype() { return TSTRING; }
79 static inline std::string null () { return ""; }
80};
81
83template<> struct FITS_traits<std::complex<float>>
84{
85 static inline int datatype() { return TCOMPLEX; }
86 static inline float null () { return 0; }
87};
88
90template<> struct FITS_traits<std::complex<double>>
91{
92 static inline int datatype() { return TDBLCOMPLEX; }
93 static inline double null () { return 0; }
94};
95
96template<typename T>
97void* FITS_void_ptr (const T& ptr)
98{
99 return const_cast<T*> (&ptr);
100}
101
102void* FITS_void_ptr (const std::string&);
103
105template<typename T>
106void psrfits_update_key (fitsfile* fptr, const char* name, T data, const char* comment = 0)
107{
108 // status
109 int status = 0;
110
111 fits_update_key (fptr, FITS_traits<T>::datatype(),
112 const_cast<char*>(name), &data,
113 const_cast<char*>(comment), &status);
114
115 if (status)
116 throw FITSError (status, "psrfits_update_key", name);
117}
118
120void psrfits_update_key (fitsfile* fptr, const char* name,
121 const char* data,
122 const char* comment = 0);
123
125void psrfits_update_key (fitsfile* fptr, const char* name,
126 const std::string& data,
127 const char* comment = 0);
128
130void psrfits_update_key (fitsfile* fptr,
131 const char* name,
132 int column,
133 const std::string& value,
134 const char* comment = 0);
135
137void psrfits_read_key (fitsfile* fptr,
138 const char* name,
139 int column,
140 std::string& value,
141 std::string& comment);
142
144template<typename T>
145void psrfits_read_key_work (fitsfile* fptr, const char* name, T* data, int* status)
146{
147 // no comment
148 char* comment = 0;
149
150 fits_read_key (fptr, FITS_traits<T>::datatype(),
151 const_cast<char*>(name), data,
152 comment, status);
153}
154
156void psrfits_read_key_work (fitsfile* fptr, const char* name, std::string*,
157 int* status);
158
160template<typename T>
161void psrfits_read_key (fitsfile* fptr, const char* name, T* data)
162{
163 // status
164 int status = 0;
165 psrfits_read_key_work (fptr, name, data, &status);
166 if (status)
167 throw FITSError (status, "psrfits_read_key", name);
168}
169
171
174template<typename Class, typename T>
175void psrfits_read_key (fitsfile* fptr, const char* name, Class* instance, void(Class::*set)(T))
176{
177 T val;
178 psrfits_read_key (fptr, name, &val);
179 (instance->*set)(val);
180}
181
183
186template<typename Class, typename T>
187void psrfits_read_key (fitsfile* fptr, const char* name, Reference::To<Class>& instance, void(Class::*set)(T))
188{
189 T val;
190 psrfits_read_key (fptr, name, &val);
191 (instance->*set)(val);
192}
193
195template<typename T>
196void psrfits_read_key (fitsfile* fptr, const char* name, T* data, T dfault, bool verbose = false)
197{
198 // status
199 int status = 0;
200 psrfits_read_key_work (fptr, name, data, &status);
201 if (status)
202 {
203 if (verbose)
204 {
205 FITSError error (status, "psrfits_read_key", name);
206 std::cerr << error.get_message() << std::endl;
207 std::cerr << "psrfits_read_key: using default=" << dfault << std::endl;
208 }
209 *data = dfault;
210 }
211 else if (verbose)
212 std::cerr << "psrfits_read_key: " << name << "=" << *data << std::endl;
213}
214
216void psrfits_update_tdim (fitsfile* ffptr, int column, unsigned dim);
217
219void psrfits_update_tdim (fitsfile* ffptr, int column,
220 unsigned dim1, unsigned dim2);
221
223void psrfits_update_tdim (fitsfile* ffptr, int column,
224 unsigned dim1, unsigned dim2, unsigned dim3);
225
227void psrfits_update_tdim (fitsfile* ffptr, int column,
228 unsigned dim1, unsigned dim2,
229 unsigned dim3, unsigned dim4);
230
232void psrfits_update_tdim (fitsfile* ffptr, int column,
233 const std::vector<unsigned>& dims);
234
235template<typename T>
236void psrfits_write_col (fitsfile* fptr, const char* name, int row,
237 const std::vector<T>& data,
238 const std::vector<unsigned>& dims)
239{
240 //
241 // Get the number of the named column
242
243 int colnum = 0;
244 int status = 0;
245
246 if (psrfits_verbose)
247 std::cerr << "psrfits_write_col calling fits_get_colnum"
248 " name='" << name << "'" << std::endl;
249
250 fits_get_colnum (fptr, CASEINSEN, const_cast<char*>(name), &colnum, &status);
251
252 if (status)
253 throw FITSError (status, "psrfits_write_col(vector<T>)",
254 "fits_get_colnum (name=%s)", name);
255
256 psrfits_write_col (fptr, colnum, row, data, dims);
257}
258
259/* when it is not feasible to write a single block of data in one go */
260template<typename Stream>
261void psrfits_write_col (fitsfile* fptr, const char* name, int row,
262 const Stream* stream)
263{
264 //
265 // Get the number of the named column
266
267 int colnum = 0;
268 int status = 0;
269
270 if (psrfits_verbose)
271 std::cerr << "psrfits_write_col calling fits_get_colnum"
272 " name='" << name << "'" << std::endl;
273
274 fits_get_colnum (fptr, CASEINSEN, const_cast<char*>(name), &colnum, &status);
275
276 if (status)
277 throw FITSError (status, "psrfits_write_col(vector<T>)",
278 "fits_get_colnum (name=%s)", name);
279
280 try
281 {
282 psrfits_write_col (fptr, colnum, row, stream);
283 }
284 catch (Error& error)
285 {
286 throw error += "psrfits_write_col(vector<T>," + std::string(name) + ")";
287 }
288}
289
290template<typename T>
291void psrfits_write_col (fitsfile* fptr, int colnum, int row,
292 const std::vector<T>& data,
293 const std::vector<unsigned>& dims)
294{
295 int status = 0;
296
297 if (psrfits_verbose)
298 std::cerr << "psrfits_write_col calling fits_modify_vector_len"
299 " colnum=" << colnum << " size=" << data.size() << std::endl;
300
301 fits_modify_vector_len (fptr, colnum, data.size(), &status);
302
303 if (status)
304 throw FITSError (status, "psrfits_write_col(vector<T>)",
305 "fits_modify_vector_len (col=%d size=%u)",
306 colnum, data.size());
307
308 if (dims.size() > 1)
309 {
310 if (psrfits_verbose)
311 std::cerr << "psrfits_write_col calling psrfits_update_tdim" << std::endl;
312
313 psrfits_update_tdim (fptr, colnum, dims);
314 }
315
316 if (psrfits_verbose)
317 std::cerr << "psrfits_write_col calling fits_write_col" << std::endl;
318
319 fits_write_col (fptr, FITS_traits<T>::datatype(),
320 colnum, row,
321 1, data.size(),
322 const_cast<T*>(&(data[0])), &status);
323
324 if (status)
325 throw FITSError (status, "psrfits_write_col(vector<T>)",
326 "fits_write_col (type=%s col=%d row=%d size=%u)",
327 fits_datatype_str(FITS_traits<T>::datatype()),
328 colnum, row, data.size());
329}
330
331template<typename Stream>
332void psrfits_write_col (fitsfile* fptr, int colnum, int row,
333 const Stream* stream)
334{
335 int status = 0;
336
337 unsigned ndat = stream->get_ndat();
338
339 if (psrfits_verbose)
340 std::cerr << "psrfits_write_col (Stream) calling fits_modify_vector_len"
341 " colnum=" << colnum << " size=" << ndat << std::endl;
342
343 fits_modify_vector_len (fptr, colnum, ndat, &status);
344
345 if (status)
346 throw FITSError (status, "psrfits_write_col(vector<T>)",
347 "fits_modify_vector_len (col=%d size=%u)",
348 colnum, ndat);
349
350 unsigned nwritten = 0;
351
352 unsigned buffer_size = 1024 * 1024;
353
354 std::vector< typename Stream::Type > tmp ( buffer_size );
355 while (nwritten < ndat)
356 {
357 if (nwritten + buffer_size > ndat)
358 buffer_size = ndat - nwritten;
359
360 stream->get_data (nwritten, buffer_size, &tmp[0] );
361
363 colnum, row,
364 nwritten + 1, buffer_size,
365 &(tmp[0]), &status);
366
367 if (status)
368 throw FITSError (status, "psrfits_write_col(Stream)",
369 "fits_write_col (type=%s col=%d row=%d size=%u)",
371 colnum, row, buffer_size);
372
373 nwritten += buffer_size;
374 }
375}
376
377template<typename T>
378void psrfits_write_col( fitsfile *fptr, const char *name, int row,
379 const T& data )
380{
381 int colnum = 0;
382 int status = 0;
383
384 fits_get_colnum (fptr, CASEINSEN, const_cast<char*>(name), &colnum, &status);
385
386 if (status)
387 throw FITSError (status, "psrfits_write_col(T)",
388 "fits_get_colnum (name=%s)", name);
389
390 try {
391 psrfits_write_col (fptr, colnum, row, data);
392 }
393 catch (Error& error)
394 {
395 throw error += "psrfits_write_col(T," + std::string(name) + ")";
396 }
397}
398
399template<typename T>
400void psrfits_write_col( fitsfile *fptr, int colnum, int row, const T& data )
401{
402 int status = 0;
403
404 fits_write_col (fptr, FITS_traits<T>::datatype(),
405 colnum, row,
406 1, 1,
407 FITS_void_ptr(data), &status);
408
409 if (status)
410 throw FITSError (status, "psrfits_write_col(T)",
411 "col=%d row=%d", colnum, row);
412}
413
414template<typename T>
415void psrfits_read_col (fitsfile* fptr, const char* name,
416 std::vector< std::vector<T> >& data,
417 int row = 1, T null = FITS_traits<T>::null())
418{
419 //
420 // Get the number of the named column
421
422 int colnum = 0;
423 int status = 0;
424
425 fits_get_colnum (fptr, CASEINSEN, const_cast<char*>(name), &colnum, &status);
426
427 int anynul = 0;
428 int counter = 1;
429
430 for (unsigned i = 0; i < data.size(); i++)
431 {
432 fits_read_col (fptr, FITS_traits<T>::datatype(),
433 colnum, row,
434 counter, data[i].size(),
435 &null, &(data[i][0]),
436 &anynul, &status);
437
438 if (status != 0)
439 throw FITSError( status, "psrfits_read_col",
440 "%s colnum=%d firstrow=%d firstelem=%d nelements=%d",
441 name, colnum, row, counter, data[i].size() );
442
443 counter += data[i].size();
444 }
445
446}
447
448template<typename T>
449void psrfits_read_col (fitsfile* fptr, const char* name, std::vector<T>& data,
450 int row = 1, T null = FITS_traits<T>::null())
451{
452 //
453 // Get the number of the named column
454
455 int colnum = 0;
456 int status = 0;
457
458 fits_get_colnum (fptr, CASEINSEN, const_cast<char*>(name), &colnum, &status);
459
460 //
461 // If the vector length is unspecified, read it from the file
462
463 if (data.size() == 0)
464 {
465 int typecode = 0;
466 long repeat = 0;
467 long width = 0;
468
469 fits_get_coltype (fptr, colnum, &typecode, &repeat, &width, &status);
470 if (status)
471 throw FITSError (status, "psrfits_read_col",
472 "fits_get_coltype (%s)", name);
473
474 data.resize( repeat );
475 }
476
477 int anynul = 0;
478 fits_read_col (fptr, FITS_traits<T>::datatype(),
479 colnum, row,
480 1, data.size(),
481 &null, &(data[0]),
482 &anynul, &status);
483
484 if (status)
485 throw FITSError (status, "psrfits_read_col", name);
486}
487
489template< typename T >
490void psrfits_read_col_work( fitsfile *fptr, const char *name, T *data,
491 int row, T null, int* status)
492{
493 int colnum = 0;
494 fits_get_colnum (fptr, CASEINSEN, const_cast<char*>(name), &colnum, status);
495
496 int anynul = 0;
497 fits_read_col( fptr, FITS_traits<T>::datatype(),
498 colnum, row,
499 1, 1, &null, data,
500 &anynul, status );
501}
502
504void psrfits_read_col_work( fitsfile *fptr, const char *name,
505 std::string *data,
506 int row, std::string& null, int* status);
507
508
509template< typename T >
510void psrfits_read_col( fitsfile *fptr, const char *name, T *data,
511 int row = 1, T null = FITS_traits<T>::null() )
512{
513 int status = 0;
514 psrfits_read_col_work (fptr, name, data, row, null, &status);
515 if (status)
516 throw FITSError (status, "psrfits_read_call", name);
517}
518
520template< typename T >
521void psrfits_read_col( fitsfile *fptr, const char *name, T *data,
522 int row, T null, T dfault, bool verbose)
523{
524 // status
525 int status = 0;
526 psrfits_read_col_work (fptr, name, data, row, null, &status);
527 if (status)
528 {
529 if (verbose)
530 {
531 FITSError error (status, "psrfits_read_col", name);
532 std::cerr << error.get_message() << std::endl;
533 std::cerr << "psrfits_read_col: using default=" << dfault << std::endl;
534 }
535 *data = dfault;
536 }
537 else if (verbose)
538 std::cerr << "psrfits_read_col: " << name << "=" << *data << std::endl;
539
540}
541
543void psrfits_init_hdu (fitsfile *fptr, const char *name, unsigned nrows=1);
544
546bool psrfits_move_hdu (fitsfile *fptr, const char *name,
547 bool optional = false,
548 int table_type = BINARY_TBL, int version = 0);
549
551void psrfits_clean_rows (fitsfile*);
552
554void psrfits_set_rows (fitsfile*, unsigned nrow);
555
557void psrfits_insert_row (fitsfile* fptr);
558
560void psrfits_delete_col (fitsfile* fptr, const char* name);
561
562#endif
A convenient exception handling class.
Definition Error.h:54
Template class manages Reference::Able objects.
Definition ReferenceTo.h:25
STL class.
STL namespace.
Empty template class requires specialization.
Definition psrfitsio.h:27

Generated using doxygen 1.14.0