PSFEstimationwithCPSO
FitsManager.cpp
00001 /*
00002  * FitsManager.cpp
00003  *
00004  *  Created on: 09/09/2012
00005  *  Author: Peter Frank Perroni (pfperroni@inf.ufpr.br)
00006  */
00007 
00008 #include "FitsManager.hpp"
00009 
00010 int FitsManager::buffer_size = 1;
00011 omp_lock_t FitsManager::mutex;
00012 
00023 FitsManager::FitsManager(int _n_zernikes, int _img_size, int _fft_size, char *obj_filename, char *_path_in, char *_path_out){
00024         path_out = _path_out;
00025         if(isFolder(_path_in)){
00026                 path_in = _path_in;
00027                 image_filename = NULL;
00028 
00029                 startup(_n_zernikes, _img_size, _fft_size, obj_filename);
00030 
00031                 multi_files = true;
00032                 listFolder(path_in, files, "fits");
00033         }
00034         else{
00035                 path_in = NULL;
00036                 image_filename = new string(_path_in);
00037 
00038                 startup(_n_zernikes, _img_size, _fft_size, obj_filename);
00039 
00040                 multi_files = false;
00041                 saved = false;
00042                 fits_size = fitsSize((char*)image_filename->c_str());
00043                 fptr_in.fptr = fptr_out_psf.fptr = fptr_out_psfinv.fptr = fptr_out_phase.fptr = fptr_out_conobj.fptr =
00044                                 fptr_out_imgdiff.fptr = NULL;
00045                 fptr_in.first_elem = fptr_out_psf.first_elem = fptr_out_psfinv.first_elem = fptr_out_phase.first_elem =
00046                                 fptr_out_conobj.first_elem = fptr_out_imgdiff.first_elem = 1;
00047                 psf_buffer.pos = psfinv_buffer.pos = phase_buffer.pos = conobj_buffer.pos = imgdiff_buffer.pos = coefs_buffer.pos = 0;
00048                 // These buffers must be double because their values will be saved to the output FITS files.
00049                 psfinv_buffer.buffer = new double[fits_size * img_area];
00050                 psf_buffer.buffer = new double[fits_size * img_area];
00051                 phase_buffer.buffer = new double[fits_size * img_area];
00052                 conobj_buffer.buffer = new double[fits_size * img_area];
00053                 imgdiff_buffer.buffer = new double[fits_size * img_area];
00054                 // Coefficients must be WORD.
00055                 coefs_buffer.buffer = new WORD[fits_size * n_zernikes];
00056         }
00057 }
00058 
00062 FitsManager::~FitsManager(){
00063         int i;
00064         for (i=0; i < buffer_size; i++){
00065                 delete buffer[i]->image;
00066                 delete buffer[i]->coefs;
00067                 delete buffer[i]->psf_generated;
00068                 delete buffer[i]->psf_inverted;
00069                 delete buffer[i]->phase_generated;
00070                 delete buffer[i]->conobj;
00071                 delete buffer[i]->img_diff;
00072                 delete buffer[i];
00073         }
00074         delete[] buffer;
00075         delete object;
00076 
00077         if(multi_files){
00078                 // Delete the filenames allocated.
00079                 for(i=files.size()-1; i >= 0; i--){
00080                         delete files[i];
00081                 }
00082         }
00083         else{
00084                 if(saved){
00085                         // Save the results to files.
00086                         char path[1024], filename[100];
00087                         getFileName((char*)image_filename->c_str(), filename);
00088                         sprintf(path, "%s/%s_psf.fits", path_out, filename);
00089                         writeFitsFile(path, &fptr_out_psf, true, psf_buffer.buffer, img_size, img_size, fits_size);
00090                         sprintf(path, "%s/%s_psfinv.fits", path_out, filename);
00091                         writeFitsFile(path, &fptr_out_psfinv, true, psfinv_buffer.buffer, img_size, img_size, fits_size);
00092                         sprintf(path, "%s/%s_phase.fits", path_out, filename);
00093                         writeFitsFile(path, &fptr_out_phase, true, phase_buffer.buffer, img_size, img_size, fits_size);
00094                         sprintf(path, "%s/%s_conobj.fits", path_out, filename);
00095                         writeFitsFile(path, &fptr_out_conobj, true, conobj_buffer.buffer, img_size, img_size, fits_size);
00096                         sprintf(path, "%s/%s_imgdiff.fits", path_out, filename);
00097                         writeFitsFile(path, &fptr_out_imgdiff, true, imgdiff_buffer.buffer, img_size, img_size, fits_size);
00098                         sprintf(path, "%s/%s_coefs.txt", path_out, filename);
00099                         save_coefs(path, coefs_buffer.buffer, fits_size, n_zernikes);
00100                 }
00101 
00102                 delete image_filename;
00103                 delete psfinv_buffer.buffer;
00104                 delete psf_buffer.buffer;
00105                 delete phase_buffer.buffer;
00106                 delete conobj_buffer.buffer;
00107                 delete imgdiff_buffer.buffer;
00108                 delete coefs_buffer.buffer;
00109         }
00110 
00111         omp_destroy_lock(&mutex);
00112 }
00113 
00119 void FitsManager::startup(int _bufer_size){
00120         buffer_size = _bufer_size;
00121 }
00122 
00131 void FitsManager::startup(int _n_zernikes, int _img_size, int _fft_size, char *obj_filepath){
00132         omp_init_lock(&mutex);
00133 
00134         n_zernikes = _n_zernikes;
00135         img_size = _img_size;
00136         fft_size = _fft_size;
00137         img_area = img_size * img_size;
00138         phase_area = fft_size * fft_size;
00139         seq_read = seq_write = 0;
00140 
00141         object = new double[img_area];
00142         if(obj_filepath != NULL){
00143                 readFitsFile(obj_filepath, object, img_area);
00144         }
00145 
00146         buffer = new fits_result*[buffer_size];
00147         for (int i=0; i < buffer_size; i++){
00148                 buffer[i] = new fits_result;
00149                 // Set the same object for all the entries in the buffer.
00150                 buffer[i]->object = object;
00151                 // Expect the FITS input image to be in double format.
00152                 buffer[i]->image = new double[img_area];
00153                 // These are the values directly calculated by the PSF estimation, thus they must be WORD.
00154                 buffer[i]->coefs = new WORD[n_zernikes];
00155                 buffer[i]->psf_generated = new WORD[img_area];
00156                 buffer[i]->psf_inverted = new WORD[img_area];
00157                 buffer[i]->phase_generated = new WORD[phase_area];
00158                 buffer[i]->conobj = new WORD[img_area];
00159                 buffer[i]->img_diff = new WORD[img_area];
00160                 buffer[i]->img_filename = image_filename;
00161                 available_buffer.push_back(buffer[i]);
00162         }
00163 }
00164 
00170 fits_result* FitsManager::nextImage(){
00171         omp_set_lock(&mutex);
00172 
00173         if (multi_files){
00174                 if(files.size() == 0){
00175                         return NULL;
00176                 }
00177         }
00178         else if(seq_read == fits_size){
00179                 return NULL;
00180         }
00181 
00182         while(available_buffer.size() == 0){
00183                 omp_unset_lock(&mutex);
00184                 usleep(1000);
00185                 omp_set_lock(&mutex);
00186         }
00187         fits_result *result = available_buffer[0];
00188         available_buffer.erase(available_buffer.begin());
00189         omp_unset_lock(&mutex);
00190 
00191         char path[1024];
00192         if (multi_files){
00193                 result->sequence = 0;
00194                 result->img_filename = files[0];
00195                 files.erase(files.begin());
00196                 sprintf(path, "%s/%s", path_in, result->img_filename->c_str());
00197                 readFitsFile(path, result->image, img_area);
00198         }
00199         else{
00200                 result->sequence = seq_read++;
00201                 readFitsFile((char*)result->img_filename->c_str(), &fptr_in, false, result->image, img_area);
00202         }
00203         memset(result->coefs, 0, n_zernikes * sizeof(WORD));
00204         memset(result->psf_generated, 0, img_area * sizeof(WORD));
00205         memset(result->psf_inverted, 0, img_area * sizeof(WORD));
00206         memset(result->phase_generated, 0, phase_area * sizeof(WORD));
00207         memset(result->conobj, 0, img_area * sizeof(WORD));
00208         memset(result->img_diff, 0, img_area * sizeof(WORD));
00209         return result;
00210 }
00211 
00221 void FitsManager::saveImage(fits_result *result){
00222         char path[1024];
00223         char *filename;
00224         if (multi_files){
00225                 // Save directly to the disk.
00226                 filename = (char*)result->img_filename->c_str();
00227                 sprintf(path, "%s/%s_psf.fits", path_out, filename);
00228                 writeFitsFile(path, result->psf_generated, img_size, img_size);
00229                 sprintf(path, "%s/%s_psfinv.fits", path_out, filename);
00230                 writeFitsFile(path, result->psf_inverted, img_size, img_size);
00231                 sprintf(path, "%s/%s_phase.fits", path_out, filename);
00232                 writeFitsFile(path, result->phase_generated, img_size, img_size);
00233                 sprintf(path, "%s/%s_conobj.fits", path_out, filename);
00234                 writeFitsFile(path, result->conobj, img_size, img_size);
00235                 sprintf(path, "%s/%s_imgdiff.fits", path_out, filename);
00236                 writeFitsFile(path, result->img_diff, img_size, img_size);
00237                 sprintf(path, "%s/%s_coefs.txt", path_out, filename);
00238                 save_coefs(path, result->coefs, 1, n_zernikes);
00239 
00240                 // Put the entry back to the buffer.
00241                 omp_set_lock(&mutex);
00242                 available_buffer.push_back(result);
00243         }
00244         else{
00245                 omp_set_lock(&mutex);
00246 
00247                 fits_result *to_write;
00248                 // Put the result in a separate list that is used to organize the output sequence.
00249                 awaiting_buffer.push_back(result);
00250                 // Guarantee that the output sequence is exactly the same as the 3D input file.
00251                 for(int i=awaiting_buffer.size()-1; i >= 0; i--){
00252                         // If this entry is the next to be written, save to the results in a secondary buffer.
00253                         if(awaiting_buffer[i]->sequence == seq_write){
00254                                 seq_write++;
00255                                 to_write = awaiting_buffer[i];
00256                                 // Remove the entry from the separate list.
00257                                 awaiting_buffer.erase(awaiting_buffer.begin() + i);
00258 
00259                                 // Save the results to the secondary buffer.
00260                                 holdData(result);
00261 
00262                                 // Put the entry back to the main buffer.
00263                                 available_buffer.push_back(to_write);
00264 
00265                                 // Reinitialize the sequencing, since the next due entry can be anywhere.
00266                                 i = awaiting_buffer.size();
00267                         }
00268                 }
00269                 saved = true;
00270         }
00271         omp_unset_lock(&mutex);
00272 }
00273 
00279 int FitsManager::size(){
00280         if (multi_files){
00281                 return files.size();
00282         }
00283         else{
00284                 return fits_size;
00285         }
00286 }
00287 
00293 double *FitsManager::getObject(){
00294         return object;
00295 }
00296 
00302 void FitsManager::holdData(fits_result *result){
00303         int i;
00304         // Depending on the WORD, this makes any necessary conversion from float to double
00305         // which is necessary to save to the output FITS file.
00306         for(i=0; i < img_area; i++, psf_buffer.pos++) psf_buffer.buffer[psf_buffer.pos] = result->psf_generated[i];
00307         for(i=0; i < img_area; i++, psfinv_buffer.pos++) psfinv_buffer.buffer[psfinv_buffer.pos] = result->psf_inverted[i];
00308         for(i=0; i < img_area; i++, phase_buffer.pos++) phase_buffer.buffer[phase_buffer.pos] = result->phase_generated[i];
00309         for(i=0; i < img_area; i++, conobj_buffer.pos++) conobj_buffer.buffer[conobj_buffer.pos] = result->conobj[i];
00310         for(i=0; i < img_area; i++, imgdiff_buffer.pos++) imgdiff_buffer.buffer[imgdiff_buffer.pos] = result->img_diff[i];
00311         for(i=0; i < n_zernikes; i++, coefs_buffer.pos++) coefs_buffer.buffer[coefs_buffer.pos] = result->coefs[i];
00312 }
00313 
00321 void FitsManager::readFitsFile(char* filename, double* image, int size) {
00322         fits_ptr ptr = {NULL, 1};
00323         return readFitsFile(filename, &ptr, true, image, size);
00324 }
00325 
00335 void FitsManager::readFitsFile(char* filename, fits_ptr *ptr, bool closeFits, double* image, int size) {
00336         omp_set_lock(&mutex);
00337         int status = 0;
00338         // Open the FITS file.
00339         if (ptr->fptr == NULL && fits_open_file(&ptr->fptr, filename, READONLY, &status)){
00340                 printerror(status);
00341                 exit(1);
00342         }
00343 
00344         // Read the FITS file at the correct sequence, based on the FITS pointer provided.
00345         int anynull;
00346         double nullval = 0;
00347         fits_read_img(ptr->fptr, TDOUBLE, ptr->first_elem, size, &nullval, image, &anynull, &status);
00348 
00349         // Close the file, if necessary.
00350         if ((status || closeFits)){
00351                 if (fits_close_file(ptr->fptr, &status)){
00352                         printerror(status);
00353                         exit(1);
00354                 }
00355         }
00356         else{
00357                 // If don't close the file, increase the sequence in the FITS pointer.
00358                 ptr->first_elem += size;
00359         }
00360         omp_unset_lock(&mutex);
00361 }
00362 
00371 int FitsManager::fitsSize(char* filename) {
00372         omp_set_lock(&mutex);
00373         fitsfile *fptr;
00374         int status = 0;
00375         if (fits_open_file(&fptr, filename, READONLY, &status)){
00376                 printerror(status);
00377                 exit(1);
00378         }
00379 
00380         int size;
00381         fits_read_key(fptr, TLONG, "NAXIS3", &size, NULL, &status);
00382         // A 2D file doesn't contain the key NAXIS3.
00383         if(status){
00384                 size = 1;
00385                 status = 0;
00386         }
00387 
00388         if (fits_close_file(fptr, &status)){
00389                 printerror(status);
00390                 exit(1);
00391         }
00392         omp_unset_lock(&mutex);
00393 
00394         return size;
00395 }
00396 
00407 void FitsManager::writeFitsFile(char* filename, WORD* array, int sx, int sy) {
00408         // Ensure that the output file data type is always double, regardless the data type currently in use.
00409         int size = sx * sy;
00410         double _array[size];
00411         // Convert the data from float to double, if necessary.
00412         for(int i=0; i < size; i++) _array[i] = array[i];
00413 
00414         fits_ptr ptr = {NULL, 1};
00415         writeFitsFile(filename, &ptr, true, _array, sx, sy, 1);
00416 }
00417 
00432 void FitsManager::writeFitsFile(char* filename, fits_ptr *ptr, bool closeFits, double* array, int sx, int sy, int sz) {
00433         omp_set_lock(&mutex);
00434         int status = 0; // initialize status before calling fitsio routines
00435         if (ptr->fptr == NULL){
00436                 // Delete old file if it already exists
00437                 remove(filename);
00438 
00439                 // create new FITS files
00440                 if (fits_create_file(&(ptr->fptr), filename, &status)){
00441                         printerror(status);
00442                         exit(1);
00443                 }
00444         }
00445 
00446     int  bitpix   =  -64;
00447     long naxis = (sz > 1) ? 3 : 2; // Specify the dimension of the image.
00448         long naxes[naxis];
00449         naxes[0] = sx; naxes[1] = sy;
00450     if(sz > 1){
00451         // Set the number of images in a 3D file.
00452         naxes[2] = sz;
00453     }
00454 
00455     // Create an entry to the image in the FITS file.
00456     if (fits_create_img(ptr->fptr, bitpix, naxis, naxes, &status)){
00457                 printerror(status);
00458         }
00459 
00460         // write the array to the FITS file
00461         long size = sx * sy * sz;
00462         if (fits_write_img(ptr->fptr, TDOUBLE, ptr->first_elem, size, array, &status)){
00463                 printerror(status);
00464         }
00465 
00466         // Close the file, if necessary.
00467         if ((status || closeFits)){
00468                 // close the file
00469                 if (fits_close_file(ptr->fptr, &status)){
00470                         printerror(status);
00471                         exit(1);
00472                 }
00473         }
00474         else{
00475                 // If don't close the file, increase the sequence in the FITS pointer.
00476                 ptr->first_elem += size;
00477         }
00478         omp_unset_lock(&mutex);
00479 }
00480 
00489 void FitsManager::save_coefs(char *file_name, WORD *coefs, int n_rows, int n_coefs){
00490         if(coefs == NULL || n_rows < 1 || n_coefs < 1 || file_name == NULL) return;
00491 
00492         // Allow a buffer with 30 chars + ", " per number, with a '\n' per line.
00493         char s_coefs[n_rows * ((n_coefs * (30 + 2)) + 1)];
00494         s_coefs[0] = '\0';
00495         for(int j, i=0; i < n_rows; i++){
00496                 for(j=0; j < n_coefs; j++){
00497                         sprintf(s_coefs, "%s%f, ", s_coefs, coefs[(i*n_coefs)+j]);
00498                 }
00499                 s_coefs[strlen(s_coefs)-1] = '\n';
00500         }
00501 
00502         FILE *fp = fopen(file_name, "w");
00503         if (!fp) {
00504                 cerr << "Failed to save coefs [" << file_name << "]." << std::endl;
00505                 return;
00506         }
00507         int sz1 = fwrite(s_coefs, 1, strlen(s_coefs), fp);
00508         if (sz1 < 1) {
00509                 cerr << "Failed to save coefs [" << file_name << "]." << std::endl;
00510         }
00511         fclose(fp);
00512 }
00513 
00519 void FitsManager::printerror(int status) {
00520         if (status) {
00521                 fits_report_error(stderr, status); /* print error report */
00522                 exit(status); /* terminate program, return error status */
00523         }
00524 }
00525 
00535 void FitsManager::listFolder(char *folder, vector<string*> &files, const char *extension) {
00536         DIR *dp;
00537         struct dirent *dirp;
00538         if ((dp = opendir(folder)) == NULL) {
00539                 cout << "Error opening " << folder << endl;
00540                 exit(1);
00541         }
00542 
00543         char ext[30];
00544         while ((dirp = readdir(dp)) != NULL) {
00545                 getFileExtension(dirp->d_name, ext);
00546                 if(strcmp(ext, extension) == 0){
00547                         files.push_back(new string(dirp->d_name));
00548                 }
00549         }
00550         closedir(dp);
00551 }
00552 
00559 bool FitsManager::isFolder(char *folder) {
00560         DIR *dp;
00561         if ((dp = opendir(folder)) == NULL) {
00562                 return false;
00563         }
00564 
00565         closedir(dp);
00566         return true;
00567 }
00568 
00575 void FitsManager::getFileName(char *fullPath, char *fileName){
00576         int i, j, pos;
00577         for(i=0; fullPath[i] != '\0'; i++){
00578                 if(fullPath[i] == '/' || fullPath[i] == '\\'){
00579                         pos = i;
00580                 }
00581         }
00582         for(j=0, pos++; pos <= i; pos++, j++){
00583                 fileName[j] = fullPath[pos];
00584         }
00585 }
00586 
00593 void FitsManager::getFileExtension(char *fullPath, char *fileExtension){
00594         int i, j, pos;
00595         for(i=0; fullPath[i] != '\0'; i++){
00596                 if(fullPath[i] == '.'){
00597                         pos = i;
00598                 }
00599         }
00600         for(pos++, j=0; pos <= i; pos++, j++){
00601                 fileExtension[j] = fullPath[pos];
00602         }
00603 }
 All Classes Functions