GLAMERDOC++
Gravitational Lensing Code Library
cpfits.h
1 //
2 // cpfits.h
3 // GLAMER
4 //
5 // Created by Robert Benton Metcalf on 24/10/2019.
6 //
7 // This is a class that is meant to replace the CCFITS library
8 // so that it can be eliminated as a dependancy.
9 //
10 // These classes are for reading from and writing to fits files.
11 // Only
12 //
13 // for more infermation of cfitio routines see :
14 // https://heasarc.gsfc.nasa.gov/docs/software/fitsio/quick/node9.html
15 
16 #ifndef cpfits_h
17 #define cpfits_h
18 
19 #include <string.h>
20 #include <iostream>
21 #include <stdio.h>
22 #include <valarray>
23 #include <map>
24 #include "fitsio.h"
25 #include <mutex>
26 
27 #include <Tree.h>
28 
29 
30 class CPFITS_BASE{
31 
32 protected:
33  CPFITS_BASE(){}
34 
35  CPFITS_BASE(CPFITS_BASE &&ff){
36  fptr = ff.fptr;
37  ff.fptr = nullptr;
38  }
39 
40  void operator=(CPFITS_BASE &&ff){
41  fptr = ff.fptr;
42  ff.fptr = nullptr;
43  }
44 
45  void check_status(int status,std::string s = "Error in CPFITS"){
46  if(status){
47  fits_report_error(stderr, status);
48  std::cerr << s << std::endl;
49  throw std::invalid_argument(s);
50  }
51  }
52  fitsfile *fptr;
53 
54  std::mutex mutex_lock;
55 public:
56 
58  // HDU-level Routines
60 
62  int get_num_hdus(){
63  std::lock_guard<std::mutex> hold(mutex_lock);
64  int hdunum;
65  int status = 0;
66  fits_get_num_hdus(fptr, &hdunum, &status);
67  check_status(status);
68  return hdunum;
69 
70  }
72  int get_current_hdu_num(){
73  std::lock_guard<std::mutex> hold(mutex_lock);
74  int hdunum;
75  fits_get_hdu_num(fptr,&hdunum);
76  return hdunum;
77  }
78 
80  int change_hdu(int i){
81  int hdunum = get_num_hdus();
82  if(i > hdunum || i < 1){
83  throw std::invalid_argument("out of range");
84  }
85  int hdutype;
86  int status = 0;
87  {
88  std::lock_guard<std::mutex> hold(mutex_lock);
89  fits_movabs_hdu(fptr,i,&hdutype,&status);
90  }
91  check_status(status);
92  reset_imageInfo();
93 
94  return hdutype;
95  }
96 
97  int get_current_hdu_type(bool verbose=false){
98 
99  int hdutype,status = 0;
100  fits_get_hdu_type(fptr,&hdutype,&status);
101  check_status(status);
102 
103  if(verbose){
104  std::cout << "type: " ;
105  switch (hdutype) {
106  case 0:
107  std::cout << "Image" << std::endl;
108  break;
109  case 1:
110  std::cout << "ASCII table" << std::endl;
111  break;
112  case 2:
113  std::cout << "Binary table" << std::endl;
114  break;
115 
116  default:
117  break;
118  }
119  }
120 
121  return hdutype;
122  }
123 
125  // image information of current HDU
127 
136  void reset_imageInfo(){
137  std::lock_guard<std::mutex> hold(mutex_lock);
138 
139  int status = 0;
140  fits_get_img_type(fptr,&bitpix,&status);
141  check_status(status);
142  fits_get_img_dim(fptr,&Ndims,&status);
143  check_status(status);
144  sizes.resize(Ndims);
145  fits_get_img_size(fptr,Ndims,sizes.data(),&status);
146  check_status(status);
147 
148  //std::cout << sizes.size() << std::endl;
149  }
150  void imageDimensions(std::vector<long> &my_sizes){
151  my_sizes.resize(sizes.size());
152  my_sizes = sizes;
153  }
154 
156  int nkyewords(){
157  std::lock_guard<std::mutex> hold(mutex_lock);
158  int keysexist,status=0;
159  return fits_get_hdrspace(fptr,&keysexist,NULL,&status);
160  }
161 
163  int readKey(std::string keyname,double &value){
164  std::lock_guard<std::mutex> hold(mutex_lock);
165  int status = 0;
166  return fits_read_key(fptr,TDOUBLE,keyname.c_str(),
167  &value,NULL,&status);
168  }
169  int readKey(std::string keyname,float &value){
170  std::lock_guard<std::mutex> hold(mutex_lock);
171  int status = 0;
172  return fits_read_key(fptr,TFLOAT,keyname.c_str(),
173  &value,NULL,&status);
174  }
175  int readKey(std::string keyname,int &value){
176  std::lock_guard<std::mutex> hold(mutex_lock);
177  int status = 0;
178  return fits_read_key(fptr,TINT,keyname.c_str(),
179  &value,NULL,&status);
180  }
181  int readKey(std::string keyname,size_t &value){
182  std::lock_guard<std::mutex> hold(mutex_lock);
183  int status = 0;
184  return fits_read_key(fptr,TULONG,keyname.c_str(),
185  &value,NULL,&status);
186  }
187  int readKey(std::string keyname,long &value){
188  std::lock_guard<std::mutex> hold(mutex_lock);
189  int status = 0;
190  return fits_read_key(fptr,TLONG,keyname.c_str(),
191  &value,NULL,&status);
192  }
193  int readHeader(std::vector<std::string> &headercards,bool verbose=false){
194  std::lock_guard<std::mutex> hold(mutex_lock);
195  int nkeys,status=0,hdupos;
196  char card[FLEN_CARD];
197 
198  headercards.clear();
199  fits_get_hdu_num(fptr, &hdupos); /* Get the current HDU position */
200  fits_get_hdrspace(fptr, &nkeys, NULL, &status); // get # of keywords
201 
202  if(verbose) printf("Header listing for HDU #%d:\n", hdupos);
203 
204  for (int ii = 1; ii <= nkeys; ii++) { // Read and print each keywords
205  if (fits_read_record(fptr, ii, card, &status))break;
206  if(verbose) printf("%s\n", card);
207  headercards.push_back(card);
208  }
209  if(verbose) printf("END\n\n"); // terminate listing with END
210 
211  //fits_movrel_hdu(fptr, 1, NULL, &status); /* try to move to next HDU */
212  return status;
213  }
214 
216  int printHeader(){
217  std::vector<std::string> cards;
218  return readHeader(cards,true);
219  }
220 
221 
222  //int fits_parse_value(char *card, char *value, char *comment, int *status)
223  //int fits_get_keytype(char *value, char *dtype, int *status)
224 
225 protected:
226  int Ndims;
227  std::vector<long> sizes;
228  int bitpix;
229 };
230 
232 class CPFITS_READ : public CPFITS_BASE {
233 private:
234  // make it uncopyable
235  //CPFITS_READ(CPFITS_READ &);
236  //CPFITS_READ operator=(CPFITS_READ );
237 
238 public:
239  CPFITS_READ(std::string filename,std::string extension=""
240  ,bool verbose = false) {
241 
242  int status = 0;
243  //fits_open_file(&fptr,filename.c_str(), READONLY, &status);
244  if(extension==""){
245  fits_open_image(&fptr,filename.c_str(), READONLY, &status);
246  }else{
247  filename = filename + extension;
248  fits_open_image(&fptr,filename.c_str(), READONLY, &status);
249  }
250  // print any error messages
251  check_status(status,"Problem with input fits file.");
252  reset_imageInfo();
253 
254  if(verbose){
255  std::cout << "Opening file : " << filename << std::endl;
256  std::cout << " status : " << status << std::endl;
257  }
258  }
259 
260  ~CPFITS_READ(){
261  int status = 0;
262  fits_close_file(fptr, &status);
263  //check_status(status,"Problem closing fits file!");
264  }
265 
266  CPFITS_READ(CPFITS_READ &&ff):CPFITS_BASE(std::move(ff)){};
267 
268  void operator=(CPFITS_READ &&ff){
269  CPFITS_BASE::operator=(std::move(ff));
270  }
271 
273  void reset(std::string filename,std::string extension=""){
274  std::lock_guard<std::mutex> hold(mutex_lock);
275  int status = 0;
276  fits_close_file(fptr, &status);
277  check_status(status);
278  //fits_open_image(&fptr,filename.c_str(), READONLY, &status);
279  if(extension==""){
280  fits_open_image(&fptr,filename.c_str(), READONLY, &status);
281  }else{
282  filename = filename + extension;
283  fits_open_image(&fptr,filename.c_str(), READONLY, &status);
284  }
285  check_status(status);
286  reset_imageInfo();
287  }
288 
290  int read(std::vector<double> &output,std::vector<long> &size){
291 
292  //int dtype;
293  imageDimensions(size);
294  long nelements=1;
295  for(long n : size) nelements *= n;
296  std::vector<long> start(size.size(),1);
297 
298  output.resize(nelements);
299  std::lock_guard<std::mutex> hold(mutex_lock);
300  int status = 0;
301  return fits_read_pix(fptr,TDOUBLE,start.data(),nelements
302  ,NULL,output.data(),NULL, &status);
303  }
305  int read(std::vector<float> &output,std::vector<long> &size){
306 
307  //int dtype;
308  imageDimensions(size);
309  long nelements=1;
310  for(long n : size) nelements *= n;
311  std::vector<long> start(size.size(),1);
312  output.resize(nelements);
313 
314  int status = 0;
315  std::lock_guard<std::mutex> hold(mutex_lock);
316  return fits_read_pix(fptr,TFLOAT,start.data(),nelements
317  ,NULL,output.data(),NULL, &status);
318  }
320  int read(std::valarray<float> &output,std::vector<long> &size){
321 
322  //int dtype;
323  imageDimensions(size);
324  long nelements=1;
325  for(long n : size) nelements *= n;
326  std::vector<long> start(size.size(),1);
327 
328  output.resize(nelements);
329 
330  int status = 0;
331  std::lock_guard<std::mutex> hold(mutex_lock);
332  return fits_read_pix(fptr,TFLOAT,start.data(),nelements
333  ,NULL,&output[0],NULL, &status);
334  }
335  int read(std::valarray<double> &output,std::vector<long> &sizes){
336  //std::cout << sizes.size() << std::endl;
337  imageDimensions(sizes);
338  //std::cout << sizes.size() << std::endl;
339  //std::cout << sizes[0] << " " << sizes[1] << std::endl;
340  long long nelements=1;
341  for(long n : sizes) nelements *= n;
342  std::vector<long> start(sizes.size(),1);
343  output.resize(nelements);
344 
345  int status = 0;
346  std::lock_guard<std::mutex> hold(mutex_lock);
347  int error = fits_read_pix(fptr,TDOUBLE,start.data(),nelements
348  ,NULL,&output[0],NULL, &status);
349  check_status(status,"PixMap Read Failure");
350 
351  return error;
352  }
353 
355  template<typename T>
356  int read(std::vector<std::vector<T> > &output){
357 
358  std::vector<long> size;
359  std::vector<T> tmp;
360  int status = read(tmp,size);
361  output.resize(size[0]);
362  size_t k = 0;
363  for(size_t i=0 ; i < size[0] ; ++i){
364  output[i].resize(size[1]);
365  for(T &x : output[i]){
366  x = tmp[k++];
367  }
368  }
369 
370  return status;
371  }
373 
375  int read_block(double *output,long nelements,long * start){
376  int status =0;
377  std::lock_guard<std::mutex> hold(mutex_lock);
378  return fits_read_pix(fptr,TDOUBLE,start,nelements
379  ,NULL,output,NULL, &status);
380  }
381  int read_block(float *output,long nelements,long * start){
382  int status = 0;
383  std::lock_guard<std::mutex> hold(mutex_lock);
384  return fits_read_pix(fptr,TFLOAT,start,nelements
385  ,NULL,output,NULL, &status);
386  }
387 
388 
390  int read_subset(double *output,long *lowerleft,long *upperright){
391  long inc[2] = {1,1}; // this is a step
392  int status = 0;
393  std::lock_guard<std::mutex> hold(mutex_lock);
394  return fits_read_subset(fptr,TDOUBLE,lowerleft,upperright,inc
395  ,NULL,output,NULL,&status);
396  }
398  int read_subset(float *output,long *lowerleft,long *upperright){
399  long inc[2] = {1,1}; // this is a step
400  int status = 0;
401  std::lock_guard<std::mutex> hold(mutex_lock);
402  return fits_read_subset(fptr,TFLOAT,lowerleft,upperright,inc
403  ,NULL,output,NULL,&status);
404  }
405 };
406 
407 class CPFITS_WRITE : public CPFITS_BASE {
408 
409 private:
410  // make it uncopyable
411  CPFITS_WRITE(CPFITS_READ &);
412  CPFITS_WRITE operator=(CPFITS_WRITE );
413 
414 public:
415  CPFITS_WRITE(std::string filename,bool append = false,bool verbose = false) {
416 
417  if(!append){
418  if(verbose) std::cout << "Creating file : " << filename << std::endl;
419  if(filename[0] != '!') filename = "!" + filename;
420  int status = 0;
421  fits_create_file(&fptr, filename.c_str(), &status);
422  check_status(status);
423  }else{
424  int status = 0;
425  fits_open_image(&fptr,filename.c_str(),READWRITE,&status);
426  reset_imageInfo();
427 
428  if(status==104){ // create file if it does not exist
429  status = 0;
430  fits_create_file(&fptr, filename.c_str(), &status);
431  check_status(status);
432 
433  if(verbose) std::cout << "Creating file : " << filename << std::endl;
434  }else{
435  if(verbose) std::cout << "Appending to file : " << filename << std::endl;
436  check_status(status);
437  }
438  }
439  }
440 
441  ~CPFITS_WRITE(){
442  int status = 0;
443  fits_close_file(fptr, &status);
444  check_status(status);
445  }
446 
448  void write_array(std::vector<double> &array){
449  long n = array.size();
450  int status=0;
451  std::lock_guard<std::mutex> hold(mutex_lock);
452  fits_create_img(fptr,DOUBLE_IMG,1,&n, &status);
453  check_status(status);
454  std::vector<long> fpixel(1,1);
455  fits_write_pix(fptr,TDOUBLE,fpixel.data(),
456  n,array.data(),&status);
457  check_status(status);
458  }
460  void write_array(std::vector<float> &array){
461  long n = array.size();
462  int status=0;
463  std::lock_guard<std::mutex> hold(mutex_lock);
464  fits_create_img(fptr,FLOAT_IMG,1,&n, &status);
465  check_status(status);
466  std::vector<long> fpixel(1,1);
467  fits_write_pix(fptr,TFLOAT,fpixel.data(),
468  n,array.data(),&status);
469  check_status(status);
470  }
471 
473  void write_image(std::vector<double> &im,std::vector<long> &size){
474  size_t n=1;
475  for(size_t i : size) n *= i;
476  assert(im.size() == n);
477  int status=0;
478  std::lock_guard<std::mutex> hold(mutex_lock);
479  fits_create_img(fptr,DOUBLE_IMG,size.size(),
480  size.data(), &status);
481  check_status(status);
482  std::vector<long> fpixel(size.size(),1);
483  fits_write_pix(fptr,TDOUBLE,fpixel.data(),
484  im.size(),im.data(),&status);
485  check_status(status);
486  }
487  void write_image(double *im,std::vector<long> &size){
488  size_t n=1;
489  for(size_t i : size) n *= i;
490  int status=0;
491  std::lock_guard<std::mutex> hold(mutex_lock);
492  fits_create_img(fptr,DOUBLE_IMG,size.size(),
493  size.data(), &status);
494  check_status(status);
495  std::vector<long> fpixel(size.size(),1);
496  fits_write_pix(fptr,TDOUBLE,fpixel.data(),
497  n,im,&status);
498  check_status(status);
499  }
500  void write_image(std::vector<float> &im,std::vector<long> &size){
501  size_t n=1;
502  for(size_t i : size) n *= i;
503  assert(im.size() == n);
504  int status = 0;
505  std::lock_guard<std::mutex> hold(mutex_lock);
506  fits_create_img(fptr,FLOAT_IMG,size.size(),
507  size.data(), &status);
508  check_status(status);
509  std::vector<long> fpixel(size.size(),1);
510  fits_write_pix(fptr,TFLOAT,fpixel.data(),
511  im.size(),im.data(),&status);
512  check_status(status);
513  }
514  void write_image(float *im,std::vector<long> &size){
515  size_t n=1;
516  for(size_t i : size) n *= i;
517  int status=0;
518  std::lock_guard<std::mutex> hold(mutex_lock);
519  fits_create_img(fptr,FLOAT_IMG,size.size(),
520  size.data(), &status);
521  check_status(status);
522  std::vector<long> fpixel(size.size(),1);
523  fits_write_pix(fptr,TFLOAT,fpixel.data(),
524  n,im,&status);
525  check_status(status);
526  }
527  void write_image(std::valarray<double> &im,std::vector<long> &size){
528  size_t n=1;
529  for(size_t i : size) n *= i;
530  assert(im.size() == n);
531  int status = 0;
532  std::lock_guard<std::mutex> hold(mutex_lock);
533  fits_create_img(fptr,DOUBLE_IMG,size.size(),
534  size.data(), &status);
535  check_status(status);
536 
537  status = 0;
538  std::vector<long> fpixel(size.size(),1);
539  fits_write_pix(fptr,TDOUBLE,fpixel.data(),
540  im.size(),&im[0],&status);
541  check_status(status);
542  }
543  void write_image(std::valarray<float> &im,std::vector<long> &size){
544  size_t n=1;
545  for(size_t i : size) n *= i;
546  assert(im.size() == n);
547  int status = 0;
548  std::lock_guard<std::mutex> hold(mutex_lock);
549  fits_create_img(fptr,FLOAT_IMG,size.size(),
550  size.data(), &status);
551  check_status(status);
552  std::vector<long> fpixel(size.size(),1);
553  fits_write_pix(fptr,TFLOAT,fpixel.data(),
554  im.size(),&im[0],&status);
555  check_status(status);
556  }
557 
559  template<typename T>
560  void write_image(std::vector<std::vector<T> > &im){
561  std::vector<long> size(2);
562  size[0] = im.size();
563  size[1] = im[0].size();
564 
565  size_t k=0;
566  std::vector<T> tmp(size[0]*size[1]);
567  for(long i=0; i<size[0] ; ++i){
568  for(long j=0; j<size[1] ; ++j){
569  tmp[k++] = im[i][j];
570  }
571  }
572 
573  write_image(tmp,size);
574  }
575 
577  int writeKey(std::string key,std::string value,std::string comment ){
578  int status = 0;
579  char *s = strdup(value.c_str());
580  std::lock_guard<std::mutex> hold(mutex_lock);
581  int error = fits_write_key(fptr,TSTRING,key.c_str(),
582  s,comment.c_str(),&status);
583  delete[] s;
584  return error;
585  }
586  int writeKey(std::string key,double value,std::string comment ){
587  int status = 0;
588  std::lock_guard<std::mutex> hold(mutex_lock);
589  return fits_update_key(fptr,TDOUBLE,key.c_str(),
590  &value,comment.c_str(),&status);
591  }
592  int writeKey(std::string key,float value,std::string comment ){
593  int status = 0;
594  std::lock_guard<std::mutex> hold(mutex_lock);
595  return fits_update_key(fptr,TFLOAT,key.c_str(),
596  &value,comment.c_str(),&status);
597  }
598  int writeKey(std::string key,int value,std::string comment ){
599  int status = 0;
600  std::lock_guard<std::mutex> hold(mutex_lock);
601  return fits_update_key(fptr,TINT,key.c_str(),
602  &value,comment.c_str(),&status);
603  }
604  int writeKey(std::string key,long value,std::string comment ){
605  int status = 0;
606  std::lock_guard<std::mutex> hold(mutex_lock);
607  return fits_update_key(fptr,TLONG,key.c_str(),
608  &value,comment.c_str(),&status);
609  }
610  int writeKey(std::string key,size_t value,std::string comment ){
611  int status = 0;
612  std::lock_guard<std::mutex> hold(mutex_lock);
613  return fits_update_key(fptr,TULONG,key.c_str(),
614  &value,comment.c_str(),&status);
615  }
616 
618  int writeHeader(std::vector<std::string> &cards){
619  int status = 0;
620  for(auto &str : cards){
621  fits_write_record(fptr, str.c_str(), &status);
622  }
623  return status;
624  }
625 
627  void copyHeader(CPFITS_BASE &input){
628  std::vector<std::string> cards;
629  input.readHeader(cards);
630  writeHeader(cards);
631  }
632 
633 };
634 
636 class CPFITS_READ_TABLES : public CPFITS_BASE {
637 private:
638  // make it uncopyable
639  //CPFITS_READ(CPFITS_READ &);
640  //CPFITS_READ operator=(CPFITS_READ );
641 
642  long Nrow; // current number of rows
643  int Ncol; // current number of columns
644 
645  void reset_tableInfo(){
646  int status = 0;
647  fits_get_num_rows(fptr, &Nrow, &status);
648  fits_get_num_cols(fptr, &Ncol, &status);
649  }
650  std::vector<std::string> col_names;
651 
652  int get_colnames(std::vector<std::string> &names){
653 
654  int status=0;
655  char colname[100];
656  std::string c = "*";
657  names.resize(Ncol);
658  int colnum;
659 
660  //for(int i=0;i<Ncol;++i){
661  //for(int i=0;i<10;++i){
662  for(auto &name : names){
663  fits_get_colname(fptr,CASESEN,(char*)(c.c_str()),colname, &colnum, &status);
664  //names[i] = colname;
665  name = colname;
666  //std::cout << i << " " << names[i] << " " << status << std::endl;
667  }
668 
669  return status;
670  }
671 public:
672 
673  CPFITS_READ_TABLES(std::string filename,int hdunum=2,bool verbose = false) {
674 
675  int status = 0;
676  fits_open_table(&fptr,filename.c_str(), READONLY, &status);
677  check_status(status,"Problem with input fits file.");
678  if(hdunum>0){
679  int num;
680  fits_get_num_hdus(fptr, &num, &status);
681  if(hdunum > num){
682  throw std::runtime_error("Not enough HDUs in " + filename);
683  }
684  int hdutype;
685  fits_movabs_hdu(fptr,hdunum, &hdutype, &status);
686  check_status(status,"Problem with input fits file. HDU "+std::to_string(hdunum));
687  if(hdutype != BINARY_TBL){
688  std::cerr << "HDU " << hdunum << " in " << filename << " is not a binary table" << std::endl;
689  throw std::runtime_error("wrong HDUs in " + filename);
690  }
691  }
692 
693  reset_tableInfo();
694  get_colnames(col_names);
695 
696  if(Nrow <= 0){
697  std::cerr << "No data was found in file " << filename << std::endl;
698  }
699 
700  if(verbose){
701  std::cout << "Opening file : " << filename << std::endl;
702  std::cout << Ncol << " columns" << std::endl;
703  std::cout << Nrow << " rows" << std::endl;
704  }
705  }
706 
708  int status = 0;
709  fits_close_file(fptr, &status);
710  }
711 
712  CPFITS_READ_TABLES(CPFITS_READ &&ff):CPFITS_BASE(std::move(ff)){};
713 
714  void operator=(CPFITS_READ_TABLES &&ff){
715  CPFITS_BASE::operator=(std::move(ff));
716  }
717 
718  long rows(){return Nrow;}
719  long ncol(){return Ncol;}
720 
721  int column_index(std::string &colname){
722  int col, status=0;
723 
724  fits_get_colnum(fptr, CASEINSEN,(char*)(colname.c_str())
725  , &col, &status);
726  try{
727  check_status(status,"Column does not exist.");
728  }catch(...){
729  std::cerr << "Missing column : " << colname << std::endl;
730  throw std::invalid_argument("missing column");
731  }
732  return col;
733  }
734 
735  std::vector<std::string> get_colnames(){return col_names;}
736 
737  int read_column(std::string &colname,std::vector<float> &vecf){
738 
739  int col, status=0,anyval=0;
740  col = column_index(colname);
741 
742  if(vecf.size() < Nrow ) vecf.resize(Nrow);
743 
744  fits_read_col_flt(fptr, col, 1, 1,Nrow,0,
745  vecf.data(),&anyval, &status);
746 
747  return status;
748  }
749  int read_column(std::string &colname,long firstsrow,long nelements,std::vector<float> &vecf,float nulval = -100){
750 
751  int status=0,anyval=0;
752  int colnum = column_index(colname);
753 
754  if(vecf.size() < nelements ) vecf.resize(nelements);
755  fits_read_col(fptr,TFLOAT,colnum, firstsrow, 1,nelements,&nulval,
756  vecf.data(),&anyval, &status);
757  check_status(status);
758 
759  return status;
760  }
761  int read_column(int colnum,long firstsrow,long nelements,std::vector<float> &vecf,float nulval = -100){
762 
763  int status=0,anyval=0;
764 
765  if(vecf.size() < nelements ) vecf.resize(nelements);
766 
767  fits_read_col(fptr,TFLOAT,colnum, firstsrow, 1,nelements,&nulval,
768  vecf.data(), &anyval, &status);
769 
770  check_status(status);
771 
772  return status;
773  }
774 
775  int read_column(std::string &colname,long firstsrow,long nelements,std::vector<double> &vecf,double nulval = -100){
776 
777  int status=0,anyval=0;
778  int colnum = column_index(colname);
779 
780  if(vecf.size() < nelements ) vecf.resize(nelements);
781  fits_read_col(fptr,TDOUBLE,colnum, firstsrow, 1,nelements,&nulval,
782  vecf.data(),&anyval, &status);
783  check_status(status);
784 
785  return status;
786  }
787  int read_column(int colnum,long firstsrow,long nelements,std::vector<double> &vecf,double nulval = -100){
788 
789  int status=0,anyval=0;
790 
791  if(vecf.size() < nelements ) vecf.resize(nelements);
792  fits_read_col(fptr,TDOUBLE,colnum, firstsrow, 1,nelements,&nulval,
793  vecf.data(),&anyval, &status);
794  check_status(status);
795 
796  return status;
797  }
798  int read_column(std::string &colname,long firstsrow,long nelements,std::vector<long> &vecf,int nulval = -100){
799 
800  int status=0,anyval=0;
801  int colnum = column_index(colname);
802 
803  if(vecf.size() < nelements ) vecf.resize(nelements);
804  fits_read_col(fptr,TLONG,colnum, firstsrow, 1,nelements,&nulval,
805  vecf.data(),&anyval, &status);
806  check_status(status);
807 
808  return status;
809  }
810  int read_column(int colnum,long firstsrow,long nelements,std::vector<long> &vecf,int nulval = -100){
811 
812  int status=0,anyval=0;
813 
814  if(vecf.size() < nelements ) vecf.resize(nelements);
815  fits_read_col(fptr,TLONG,colnum, firstsrow, 1,nelements,&nulval,
816  vecf.data(),&anyval, &status);
817  check_status(status);
818 
819  return status;
820  }
821 
822 
824  int gettype(int colnum){
825  int typecode,status=0;
826  long repeat,width;
827  fits_get_coltype(fptr,colnum,&typecode,
828  &repeat,&width,&status);
829  check_status(status);
830 
831  return typecode;
832  }
833 
834  int read_column(int col_index,std::vector<float> &vecf){
835 
836  int status=0,anyval=0;
837 
838  if(col_index < 1){
839  std::cerr << "CPFITS: column number must be > 0" << std::endl;
840  throw std::invalid_argument("Error in CPFITS");
841  }
842  if(col_index > Ncol){
843  std::cerr << "CPFITS: there are only " << Ncol << " columns." << std::endl;
844  throw std::invalid_argument("Error in CPFITS");
845  }
846  if(vecf.size() < Nrow ) vecf.resize(Nrow);
847 
848  fits_read_col_flt(fptr, col_index, 1, 1,Nrow,0,
849  vecf.data(),&anyval, &status);
850 
851  return status;
852  }
853 
854 
855  template <typename T>
856  void read(std::vector<T> data,int ncol){
857 
858  int status = 0,anyval=0;
859  long i, n, nread, ntodo, nrest;
860  long buffer_size = 20000;
861  std::vector<float> fitscol(buffer_size);
862 
863  for(int col = 1 ; col != ncol ; ++col){
864  nread = 0;
865  nrest = n;
866  while (nrest) {
867  //ntodo = MIN(nrest,buffer_size);
868  ntodo = (nrest < buffer_size) ? nrest : buffer_size;
869  fits_read_col_flt(fptr, col, nread + 1, 1, ntodo, 0,
870  fitscol.data(),&anyval, &status);
871  for (i = 0; i < ntodo; i++) data[i + nread][col-1] = fitscol[i];
872  nread += ntodo;
873  nrest -= ntodo;
874  }
875  }
876  }
877 };
878 
879 /*** \brief Data frame for reading fits tables and minipulating the results.
880 
881  Missing entries are replaced with -100
882  */
883 
884  template< typename T>
885  class DataFrameFits{
886 
887  private:
888  std::map<std::string,int> datamap;
889  std::vector<std::string> all_column_names;
890  std::vector<std::string> used_column_names;
891  std::string filename;
892  CPFITS_READ_TABLES cpfits;
893  std::vector<std::vector<T> > data;
894  long n0;
895  std::vector<int> column_index;
896 
897  public:
899  DataFrameFits(
900  std::string datafile
901  ,std::vector<std::string> &columns
902  ,int hdu = 2
903  ,bool verbose = false
904  ):filename(datafile),cpfits(filename,hdu,verbose),n0(1){
905 
906  all_column_names = cpfits.get_colnames();
907 
908  if(columns.size() == 0){
909  used_column_names = all_column_names;
910  }else{
911  used_column_names = columns;
912  }
913 
914  std::cout << "Reading " << used_column_names.size() << " columns." << std::endl;
915 
916  for(std::string a : used_column_names){
917  column_index.push_back(cpfits.column_index(a));
918  }
919 
920  for(int i=0 ; i<used_column_names.size() ; ++i){
921  datamap[used_column_names[i]] = i;
922  }
923 
924  data.resize(column_index.size());
925  };
926 
928  std::vector<std::string> get_all_columnnames(){return all_column_names;}
929  std::vector<std::string> get_used_columnnames(){return all_column_names;}
930 
931  // clear data
932  void clear(){
933  n0=1;
934  int ncol=data.size();
935  for(int i=0; i<ncol ; ++i){
936  data[i].clear();
937  }
938  }
939 
946  int read(
947  std::vector<std::function<bool(T &)> > &accept
948  ,bool add=false
949  ,long maxsize = -1
950  ){
951  long chunksize = 10000;
952  int ncol = column_index.size();
953  long nrow = cpfits.rows();
954  int requirements = accept.size();
955 
956  if(add){
957  n0=1;
958  }else{
959  for(int i=0; i<ncol ; ++i){
960  data[i].clear();
961  }
962  }
963 
964  if(maxsize > 0) nrow = MIN(maxsize + n0,nrow);
965 
966  if(requirements > ncol){
967  throw std::invalid_argument("Too many requirments");
968  }
969 
970  std::vector<std::vector<T> > tdata(ncol);
971  while(n0 < nrow){
972  chunksize = MIN(nrow-n0+1,chunksize);
973 
974  if(data[0].capacity() - data[0].size() < chunksize ){
975  for(int i=0; i<ncol ; ++i){
976  data[i].reserve(chunksize + data[i].capacity());
977  }
978  }
979 
980  for(int i=0 ; i< ncol ; ++i){
981  cpfits.read_column(column_index[i],n0,chunksize,tdata[i]);
982  }
983  n0 += chunksize;
984 
985  for(long j = 0 ; j < chunksize ; ++j){
986  bool accpt = true;
987  for(int i=0; i<requirements; ++i){
988  accpt *= accept[i](tdata[i][j]);
989  }
990 
991  if(accpt){
992  for(int i=0; i<ncol ; ++i){
993  data[i].push_back( tdata[i][j] ) ;
994  }
995  }
996 
997  }
998  }
999 
1000  return 1;
1001  };
1002 
1003  size_t read(
1004  std::function<bool(T,T)> &binary_accept
1005  ,std::pair<int,int> index_binary
1006  ,std::vector<std::function<bool(T &)> > &unary_accept
1007  ,std::vector<int> index_unary
1008  ,bool add=false
1009  ,long maxsize = -1
1010  ){
1011  long chunksize = 10000;
1012  int ncol = column_index.size();
1013  long nrow = cpfits.rows();
1014 
1015  if(unary_accept.size() != index_unary.size() ) throw std::invalid_argument("index_unary wrong sized ");
1016 
1017  if(add){
1018  n0=1;
1019  }else{
1020  for(int i=0; i<ncol ; ++i){
1021  data[i].clear();
1022  }
1023  }
1024 
1025  if(maxsize > 0) nrow = MIN(maxsize + n0,nrow);
1026 
1027  if(index_unary.size() > ncol){
1028  throw std::invalid_argument("Too many requirments");
1029  }
1030 
1031  std::vector<std::vector<T> > tdata(ncol);
1032  while(n0 < nrow){
1033  chunksize = MIN(nrow-n0+1,chunksize);
1034 
1035  if(data[0].capacity() - data[0].size() < chunksize ){
1036  for(int i=0; i<ncol ; ++i){
1037  data[i].reserve(chunksize + data[i].capacity());
1038  }
1039  }
1040 
1041  for(int i=0 ; i< ncol ; ++i){
1042  cpfits.read_column(column_index[i],n0,chunksize,tdata[i]);
1043  }
1044  n0 += chunksize;
1045 
1046  for(long j = 0 ; j < chunksize ; ++j){
1047 
1048  bool accpt = binary_accept(tdata[index_binary.first][j],tdata[index_binary.second][j] );
1049 
1050  int k=0;
1051  for(int i : index_unary){
1052  accpt *= unary_accept[k++]( tdata[i][j] );
1053  }
1054 
1055  if( accpt ){
1056  for(int i=0; i<ncol ; ++i){
1057  data[i].push_back( tdata[i][j] ) ;
1058  }
1059  }
1060 
1061  }
1062  }
1063 
1064  return data.size();
1065  }
1066 
1068  int read(long maxsize=-1){
1069  int ncol = column_index.size();
1070  long nrow = cpfits.rows();
1071  if(maxsize==-1) maxsize = nrow;
1072 
1073  long chunksize = nrow-n0+1;
1074  //chunksize = MIN(maxsize,chunksize);
1075  chunksize = (maxsize < chunksize) ? maxsize : chunksize;
1076 
1077  for(int i=0 ; i< ncol ; ++i){
1078  cpfits.read_column(column_index[i],n0,chunksize,data[i]);
1079  }
1080  n0 += chunksize;
1081 
1082  return 1;
1083  }
1084 
1086  std::vector<std::vector<T> > ranges(bool verbose){
1087  std::vector<std::vector<T> > ranges;
1088  int ncol = column_index.size();
1089  long nrow = cpfits.rows();
1090  long chunksize = 100000;
1091 
1092  ranges.resize(ncol);
1093  for(auto &v : ranges) v.resize(2);
1094 
1095  std::vector<T> tdata;
1096  for(int i=0 ; i< ncol ; ++i){
1097  cpfits.read_column(column_index[i],1,1,tdata);
1098  for(T a : tdata){
1099  ranges[i][0] = a;
1100  ranges[i][1] = a;
1101  }
1102  }
1103 
1104 
1105  long n=2;
1106  while(n < nrow){
1107 
1108  //chunksize = MIN(nrow-n+1,chunksize);
1109  chunksize = (nrow-n+1 < chunksize) ? nrow-n+1 : chunksize;
1110 
1111 
1112  for(int i=0 ; i< ncol ; ++i){
1113  cpfits.read_column(column_index[i],n,chunksize,tdata);
1114  for(T a : tdata){
1115  ranges[i][0] = MIN(a,ranges[i][0]);
1116  ranges[i][1] = MAX(a,ranges[i][1]);
1117  }
1118  }
1119  n += chunksize;
1120  }
1121 
1122  if(verbose){
1123  for(int i=0 ; i< ncol ; ++i){
1124  std::cout << ranges[i][0] << " <= " << used_column_names[i] << " <= " << ranges[i][1] << std::endl;
1125  }
1126  }
1127 
1128  return ranges;
1129  }
1130 
1132  std::vector<T>& operator[](const std::string &label){
1133  if(datamap.find(label) == datamap.end()){
1134  std::cerr << "No label - " << label << " - in " << filename <<std::endl;
1135  throw std::invalid_argument("no label");
1136  }
1137  return data[datamap[label]];
1138  for(auto c : all_column_names ) std::cout << c << " ";
1139  std::cout << std::endl;
1140  throw std::invalid_argument(label + " was not one of the columns of the galaxy data file :" + filename);
1141  };
1142 
1143  const std::vector<T>& operator[](const std::string &label) const{
1144  if(datamap.find(label) == datamap.end()){
1145  std::cerr << "No label - " << label << " - in " << filename <<std::endl;
1146  throw std::invalid_argument("no label");
1147  }
1148  return data[datamap[label]];
1149  for(auto c : all_column_names ) std::cout << c << " ";
1150  std::cout << std::endl;
1151  throw std::invalid_argument(label + " was not one of the columns of the galaxy data file :" + filename);
1152  };
1153 
1155  std::vector<T>& operator[](int i){
1156  return data[i];
1157  };
1158 
1159  const std::vector<T> &operator[](int i) const{
1160  return data[i];
1161  };
1162 
1164  void sortby(std::string name){
1165  std::vector<size_t> index(data[0].size());
1166  size_t N = index.size();
1167  for(size_t i=0 ; i<N ; ++i) index[i] = i;
1168 
1169  Utilities::sort_indexes(data[datamap[name]],index);
1170  std::vector<T> tmp_v(N);
1171 
1172  for(size_t j=0 ; j<data.size() ; ++j){
1173  for(size_t i=0 ; i<N ; ++i){
1174  tmp_v[i] = data[j][index[i]];
1175  }
1176  swap(data[j],tmp_v);
1177  }
1178  }
1179 
1181  void filter(const std::vector<long> &index){
1182 
1183  std::vector<T> tmp_v(index.size());
1184  for(size_t j=0 ; j<data.size() ; ++j){
1185  for(size_t i=0 ; i<index.size() ; ++i){
1186  tmp_v[i] = data[j][index[i]];
1187  }
1188  data[j] = tmp_v;
1189  }
1190  }
1191 
1193  void addColumn(std::string name){
1194  int nc = number_of_columns();
1195  long nr = number_of_rows();
1196  data.emplace_back(nr);
1197  all_column_names.push_back(name);
1198  used_column_names.push_back(name);
1199  datamap[name] = nc;
1200  //column_index.push_back(nc);
1201  }
1202 
1203  size_t number_of_rows(){return data[0].size();}
1204  size_t number_of_columns(){return data.size();}
1205 
1206 };
1207 #endif /* cpfits_h */
to_string
std::string to_string(const Band &band)
convert a Band type to a string name.
Definition: InputParams.cpp:878
CPFITS_READ
read only fits file interface
Definition: cpfits.h:232
CPFITS_READ::read_subset
int read_subset(float *output, long *lowerleft, long *upperright)
read a rectangular subset of the image
Definition: cpfits.h:398
CPFITS_READ::read
int read(std::vector< float > &output, std::vector< long > &size)
read the whole image into a vector
Definition: cpfits.h:305
CPFITS_READ::read
int read(std::vector< std::vector< T > > &output)
read the whole image into a vector
Definition: cpfits.h:356
CPFITS_READ::read
int read(std::valarray< float > &output, std::vector< long > &size)
read the whole image into a valarray
Definition: cpfits.h:320
CPFITS_READ::read_block
int read_block(double *output, long nelements, long *start)
read the whole image into a vector
Definition: cpfits.h:375
CPFITS_READ::reset
void reset(std::string filename, std::string extension="")
close old and reopen a new file
Definition: cpfits.h:273
Utilities::sort_indexes
void sort_indexes(const std::vector< T > &v, std::vector< size_t > &index)
Find the indexes that sort a vector in asending order.
Definition: utilities_slsim.h:1227
CPFITS_READ_TABLES::gettype
int gettype(int colnum)
get data type of column
Definition: cpfits.h:824
CPFITS_READ::read_subset
int read_subset(double *output, long *lowerleft, long *upperright)
read a rectangular subset of the image
Definition: cpfits.h:390
CPFITS_READ_TABLES
read only fits file interface
Definition: cpfits.h:636
CPFITS_READ::read
int read(std::vector< double > &output, std::vector< long > &size)
read the whole image into a vector
Definition: cpfits.h:290