PSFEstimationwithCPSO
|
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 }