GLAMERDOC++
Gravitational Lensing Code Library
Loading...
Searching...
No Matches
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
30class CPFITS_BASE{
31
32protected:
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;
55public:
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
225protected:
226 int Ndims;
227 std::vector<long> sizes;
228 int bitpix;
229};
230
232class CPFITS_READ : public CPFITS_BASE {
233private:
234 // make it uncopyable
235 //CPFITS_READ(CPFITS_READ &);
236 //CPFITS_READ operator=(CPFITS_READ );
237
238public:
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
407class CPFITS_WRITE : public CPFITS_BASE {
408
409private:
410 // make it uncopyable
411 CPFITS_WRITE(CPFITS_READ &);
412 CPFITS_WRITE operator=(CPFITS_WRITE );
413
414public:
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
636class CPFITS_READ_TABLES : public CPFITS_BASE {
637private:
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 }
671public:
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 check_status(status,"Column does not exist.");
727
728 return col;
729 }
730
731 std::vector<std::string> get_colnames(){return col_names;}
732
733 int read_column(std::string &colname,std::vector<float> &vecf){
734
735 int col, status=0,anyval=0;
736 col = column_index(colname);
737
738 if(vecf.size() < Nrow ) vecf.resize(Nrow);
739
740 fits_read_col_flt(fptr, col, 1, 1,Nrow,0,
741 vecf.data(),&anyval, &status);
742
743 return status;
744 }
745 int read_column(std::string &colname,long firstsrow,long nelements,std::vector<float> &vecf,float nulval = -100){
746
747 int status=0,anyval=0;
748 int colnum = column_index(colname);
749
750 if(vecf.size() < nelements ) vecf.resize(nelements);
751 fits_read_col(fptr,TFLOAT,colnum, firstsrow, 1,nelements,&nulval,
752 vecf.data(),&anyval, &status);
753 check_status(status);
754
755 return status;
756 }
757 int read_column(int colnum,long firstsrow,long nelements,std::vector<float> &vecf,float nulval = -100){
758
759 int status=0,anyval=0;
760
761 if(vecf.size() < nelements ) vecf.resize(nelements);
762
763 fits_read_col(fptr,TFLOAT,colnum, firstsrow, 1,nelements,&nulval,
764 vecf.data(), &anyval, &status);
765
766 check_status(status);
767
768 return status;
769 }
770
771 int read_column(std::string &colname,long firstsrow,long nelements,std::vector<double> &vecf,double nulval = -100){
772
773 int status=0,anyval=0;
774 int colnum = column_index(colname);
775
776 if(vecf.size() < nelements ) vecf.resize(nelements);
777 fits_read_col(fptr,TDOUBLE,colnum, firstsrow, 1,nelements,&nulval,
778 vecf.data(),&anyval, &status);
779 check_status(status);
780
781 return status;
782 }
783 int read_column(int colnum,long firstsrow,long nelements,std::vector<double> &vecf,double nulval = -100){
784
785 int status=0,anyval=0;
786
787 if(vecf.size() < nelements ) vecf.resize(nelements);
788 fits_read_col(fptr,TDOUBLE,colnum, firstsrow, 1,nelements,&nulval,
789 vecf.data(),&anyval, &status);
790 check_status(status);
791
792 return status;
793 }
794 int read_column(std::string &colname,long firstsrow,long nelements,std::vector<long> &vecf,int nulval = -100){
795
796 int status=0,anyval=0;
797 int colnum = column_index(colname);
798
799 if(vecf.size() < nelements ) vecf.resize(nelements);
800 fits_read_col(fptr,TLONG,colnum, firstsrow, 1,nelements,&nulval,
801 vecf.data(),&anyval, &status);
802 check_status(status);
803
804 return status;
805 }
806 int read_column(int colnum,long firstsrow,long nelements,std::vector<long> &vecf,int nulval = -100){
807
808 int status=0,anyval=0;
809
810 if(vecf.size() < nelements ) vecf.resize(nelements);
811 fits_read_col(fptr,TLONG,colnum, firstsrow, 1,nelements,&nulval,
812 vecf.data(),&anyval, &status);
813 check_status(status);
814
815 return status;
816 }
817
818
820 int gettype(int colnum){
821 int typecode,status=0;
822 long repeat,width;
823 fits_get_coltype(fptr,colnum,&typecode,
824 &repeat,&width,&status);
825 check_status(status);
826
827 return typecode;
828 }
829
830 int read_column(int column_index,std::vector<float> &vecf){
831
832 int status=0,anyval=0;
833
834 if(column_index < 1){
835 std::cerr << "CPFITS: column number must be > 0" << std::endl;
836 throw std::invalid_argument("Error in CPFITS");
837 }
838 if(column_index > Ncol){
839 std::cerr << "CPFITS: there are only " << Ncol << " columns." << std::endl;
840 throw std::invalid_argument("Error in CPFITS");
841 }
842 if(vecf.size() < Nrow ) vecf.resize(Nrow);
843
844 fits_read_col_flt(fptr, column_index, 1, 1,Nrow,0,
845 vecf.data(),&anyval, &status);
846
847 return status;
848 }
849
850
851 template <typename T>
852 void read(std::vector<T> data,int ncol){
853
854 int status = 0,anyval=0;
855 long i, n, nread, ntodo, nrest;
856 long buffer_size = 20000;
857 std::vector<float> fitscol(buffer_size);
858
859 for(int col = 1 ; col != ncol ; ++col){
860 nread = 0;
861 nrest = n;
862 while (nrest) {
863 //ntodo = MIN(nrest,buffer_size);
864 ntodo = (nrest < buffer_size) ? nrest : buffer_size;
865 fits_read_col_flt(fptr, col, nread + 1, 1, ntodo, 0,
866 fitscol.data(),&anyval, &status);
867 for (i = 0; i < ntodo; i++) data[i + nread][col-1] = fitscol[i];
868 nread += ntodo;
869 nrest -= ntodo;
870 }
871 }
872 }
873};
874
875/*** \brief Data frame for reading fits tables and minipulating the results.
876
877 Missing entries are replaced with -100
878 */
879
880 template< typename T>
881 class DataFrameFits{
882
883 private:
884 std::map<std::string,int> datamap;
885 std::vector<std::string> all_column_names;
886 std::vector<std::string> used_column_names;
887 std::string filename;
888 CPFITS_READ_TABLES cpfits;
889 std::vector<std::vector<T> > data;
890 long n0;
891 std::vector<int> column_index;
892
893 public:
895 DataFrameFits(
896 std::string datafile
897 ,std::vector<std::string> &columns
898 ,int hdu = 2
899 ,bool verbose = false
900 ):filename(datafile),cpfits(filename,hdu,verbose),n0(1){
901
902 all_column_names = cpfits.get_colnames();
903
904 if(columns.size() == 0){
905 used_column_names = all_column_names;
906 }else{
907 used_column_names = columns;
908 }
909
910 std::cout << "Reading " << used_column_names.size() << " columns." << std::endl;
911
912 for(std::string a : used_column_names){
913 column_index.push_back(cpfits.column_index(a));
914 }
915
916 for(int i=0 ; i<used_column_names.size() ; ++i){
917 datamap[used_column_names[i]] = i;
918 }
919
920 data.resize(column_index.size());
921 };
922
924 std::vector<std::string> get_all_columnnames(){return all_column_names;}
925 std::vector<std::string> get_used_columnnames(){return all_column_names;}
926
927 // clear data
928 void clear(){
929 n0=1;
930 int ncol=data.size();
931 for(int i=0; i<ncol ; ++i){
932 data[i].clear();
933 }
934 }
935
942 int read(
943 std::vector<std::function<bool(T &)> > &accept
944 ,bool add=false
945 ,long maxsize = -1
946 ){
947 long chunksize = 10000;
948 int ncol = column_index.size();
949 long nrow = cpfits.rows();
950 int requirements = accept.size();
951
952 if(add){
953 n0=1;
954 }else{
955 for(int i=0; i<ncol ; ++i){
956 data[i].clear();
957 }
958 }
959
960 if(maxsize > 0) nrow = MIN(maxsize + n0,nrow);
961
962 if(requirements > ncol){
963 throw std::invalid_argument("Too many requirments");
964 }
965
966 std::vector<std::vector<T> > tdata(ncol);
967 while(n0 < nrow){
968 chunksize = MIN(nrow-n0+1,chunksize);
969
970 if(data[0].capacity() - data[0].size() < chunksize ){
971 for(int i=0; i<ncol ; ++i){
972 data[i].reserve(chunksize + data[i].capacity());
973 }
974 }
975
976 for(int i=0 ; i< ncol ; ++i){
977 cpfits.read_column(column_index[i],n0,chunksize,tdata[i]);
978 }
979 n0 += chunksize;
980
981 for(long j = 0 ; j < chunksize ; ++j){
982 bool accpt = true;
983 for(int i=0; i<requirements; ++i){
984 accpt *= accept[i](tdata[i][j]);
985 }
986
987 if(accpt){
988 for(int i=0; i<ncol ; ++i){
989 data[i].push_back( tdata[i][j] ) ;
990 }
991 }
992
993 }
994 }
995
996 return 1;
997 };
998
999 size_t read(
1000 std::function<bool(T,T)> &binary_accept
1001 ,std::pair<int,int> index_binary
1002 ,std::vector<std::function<bool(T &)> > &unary_accept
1003 ,std::vector<int> index_unary
1004 ,bool add=false
1005 ,long maxsize = -1
1006 ){
1007 long chunksize = 10000;
1008 int ncol = column_index.size();
1009 long nrow = cpfits.rows();
1010
1011 if(unary_accept.size() != index_unary.size() ) throw std::invalid_argument("index_unary wrong sized ");
1012
1013 if(add){
1014 n0=1;
1015 }else{
1016 for(int i=0; i<ncol ; ++i){
1017 data[i].clear();
1018 }
1019 }
1020
1021 if(maxsize > 0) nrow = MIN(maxsize + n0,nrow);
1022
1023 if(index_unary.size() > ncol){
1024 throw std::invalid_argument("Too many requirments");
1025 }
1026
1027 std::vector<std::vector<T> > tdata(ncol);
1028 while(n0 < nrow){
1029 chunksize = MIN(nrow-n0+1,chunksize);
1030
1031 if(data[0].capacity() - data[0].size() < chunksize ){
1032 for(int i=0; i<ncol ; ++i){
1033 data[i].reserve(chunksize + data[i].capacity());
1034 }
1035 }
1036
1037 for(int i=0 ; i< ncol ; ++i){
1038 cpfits.read_column(column_index[i],n0,chunksize,tdata[i]);
1039 }
1040 n0 += chunksize;
1041
1042 for(long j = 0 ; j < chunksize ; ++j){
1043
1044 bool accpt = binary_accept(tdata[index_binary.first][j],tdata[index_binary.second][j] );
1045
1046 int k=0;
1047 for(int i : index_unary){
1048 accpt *= unary_accept[k++]( tdata[i][j] );
1049 }
1050
1051 if( accpt ){
1052 for(int i=0; i<ncol ; ++i){
1053 data[i].push_back( tdata[i][j] ) ;
1054 }
1055 }
1056
1057 }
1058 }
1059
1060 return data.size();
1061 }
1062
1064 int read(long maxsize=-1){
1065 int ncol = column_index.size();
1066 long nrow = cpfits.rows();
1067 if(maxsize==-1) maxsize = nrow;
1068
1069 long chunksize = nrow-n0+1;
1070 //chunksize = MIN(maxsize,chunksize);
1071 chunksize = (maxsize < chunksize) ? maxsize : chunksize;
1072
1073 for(int i=0 ; i< ncol ; ++i){
1074 cpfits.read_column(column_index[i],n0,chunksize,data[i]);
1075 }
1076 n0 += chunksize;
1077
1078 return 1;
1079 }
1080
1082 std::vector<std::vector<T> > ranges(bool verbose){
1083 std::vector<std::vector<T> > ranges;
1084 int ncol = column_index.size();
1085 long nrow = cpfits.rows();
1086 long chunksize = 100000;
1087
1088 ranges.resize(ncol);
1089 for(auto &v : ranges) v.resize(2);
1090
1091 std::vector<T> tdata;
1092 for(int i=0 ; i< ncol ; ++i){
1093 cpfits.read_column(column_index[i],1,1,tdata);
1094 for(T a : tdata){
1095 ranges[i][0] = a;
1096 ranges[i][1] = a;
1097 }
1098 }
1099
1100
1101 long n=2;
1102 while(n < nrow){
1103
1104 //chunksize = MIN(nrow-n+1,chunksize);
1105 chunksize = (nrow-n+1 < chunksize) ? nrow-n+1 : chunksize;
1106
1107
1108 for(int i=0 ; i< ncol ; ++i){
1109 cpfits.read_column(column_index[i],n,chunksize,tdata);
1110 for(T a : tdata){
1111 ranges[i][0] = MIN(a,ranges[i][0]);
1112 ranges[i][1] = MAX(a,ranges[i][1]);
1113 }
1114 }
1115 n += chunksize;
1116 }
1117
1118 if(verbose){
1119 for(int i=0 ; i< ncol ; ++i){
1120 std::cout << ranges[i][0] << " <= " << used_column_names[i] << " <= " << ranges[i][1] << std::endl;
1121 }
1122 }
1123
1124 return ranges;
1125 }
1126
1128 std::vector<T>& operator[](const std::string &label){
1129 if(datamap.find(label) == datamap.end()){
1130 std::cerr << "No label - " << label << " - in " << filename <<std::endl;
1131 throw std::invalid_argument("no label");
1132 }
1133 return data[datamap[label]];
1134 for(auto c : all_column_names ) std::cout << c << " ";
1135 std::cout << std::endl;
1136 throw std::invalid_argument(label + " was not one of the columns of the galaxy data file :" + filename);
1137 };
1138
1140 std::vector<T>& operator[](int i){
1141 return data[i];
1142 };
1143
1144 // sort by one of the columns in ascending order
1145 void sortby(std::string name){
1146 std::vector<size_t> index(data[0].size());
1147 size_t N = index.size();
1148 for(size_t i=0 ; i<N ; ++i) index[i] = i;
1149
1150 Utilities::sort_indexes(data[datamap[name]],index);
1151 std::vector<T> tmp_v(N);
1152
1153 for(size_t j=0 ; j<data.size() ; ++j){
1154 for(size_t i=0 ; i<N ; ++i){
1155 tmp_v[i] = data[j][index[i]];
1156 }
1157 swap(data[j],tmp_v);
1158 }
1159 }
1160
1162 void addColumn(std::string name){
1163 int nc = number_of_columns();
1164 long nr = number_of_rows();
1165 data.emplace_back(nr);
1166 all_column_names.push_back(name);
1167 used_column_names.push_back(name);
1168 datamap[name] = nc;
1169 //column_index.push_back(nc);
1170 }
1171
1172 size_t number_of_rows(){return data[0].size();}
1173 size_t number_of_columns(){return data.size();}
1174
1175};
1176#endif /* cpfits_h */
read only fits file interface
Definition cpfits.h:636
int gettype(int colnum)
get data type of column
Definition cpfits.h:820
read only fits file interface
Definition cpfits.h:232
int read(std::vector< double > &output, std::vector< long > &size)
read the whole image into a vector
Definition cpfits.h:290
int read_subset(float *output, long *lowerleft, long *upperright)
read a rectangular subset of the image
Definition cpfits.h:398
int read_subset(double *output, long *lowerleft, long *upperright)
read a rectangular subset of the image
Definition cpfits.h:390
int read(std::valarray< float > &output, std::vector< long > &size)
read the whole image into a valarray
Definition cpfits.h:320
int read(std::vector< float > &output, std::vector< long > &size)
read the whole image into a vector
Definition cpfits.h:305
int read(std::vector< std::vector< T > > &output)
read the whole image into a vector
Definition cpfits.h:356
void reset(std::string filename, std::string extension="")
close old and reopen a new file
Definition cpfits.h:273
int read_block(double *output, long nelements, long *start)
read the whole image into a vector
Definition cpfits.h:375
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:1171