PSFEstimationwithCPSO
|
00001 /* 00002 * kippe.cpp 00003 * 00004 * Created on: 27/05/2012 00005 * Author: Peter Frank Perroni (pfperroni@inf.ufpr.br) 00006 */ 00007 00008 #include "kippef.hpp" 00009 00010 void show_usage(); 00011 00015 int main(int argc, char *argv[]) 00016 { 00017 // Initialize the parameters. 00018 char *objectname = NULL; 00019 char *imgpath = NULL; 00020 char *outpath = NULL; 00021 int image_size = -1; 00022 int n_zernikes = -1; 00023 int fft_size = -1; 00024 int n_swarms = -1; 00025 int n_particles = -1; 00026 int n_cycles = -1; 00027 float w = -1, c1 = -1, c2 = -1, reset = -1; 00028 int n_validations = -1, rank_size = -1; 00029 int n_images_gen = -1; 00030 int poisson = 0; 00031 int parallel = 1; 00032 bool PSF_validation = false; 00033 bool gen_images = false; 00034 bool statistics = false; 00035 bool rms_contrast = false; 00036 bool sum = false; 00037 vector<int> *devices = NULL; 00038 int prange = 2; 00039 00040 // Read the arguments passed on command line. 00041 for(int i=1; i < argc; i++){ 00042 if(strcmp("-h", argv[i]) == 0){ 00043 show_usage(); 00044 return 0; 00045 } 00046 else if(strcmp("-testgpu", argv[i]) == 0){ 00047 test_gpu(); 00048 return 0; 00049 } 00050 else if(strcmp("-listgpu", argv[i]) == 0){ 00051 list_gpu(); 00052 return 0; 00053 } 00054 else if(strcmp("-rms_contrast", argv[i]) == 0){ 00055 rms_contrast = true; 00056 } 00057 else if(strcmp("-sum", argv[i]) == 0){ 00058 sum = true; 00059 } 00060 else if(strcmp("-obj", argv[i]) == 0){ 00061 objectname = argv[++i]; 00062 } 00063 else if(strcmp("-img", argv[i]) == 0){ 00064 imgpath = argv[++i]; 00065 } 00066 else if(strcmp("-out", argv[i]) == 0){ 00067 outpath = argv[++i]; 00068 } 00069 else if(strcmp("-fixedrand", argv[i]) == 0){ 00070 srand(RAND_SEED); 00071 } 00072 else if(strcmp("-isz", argv[i]) == 0){ 00073 image_size = atoi(argv[++i]); 00074 } 00075 else if(strcmp("-fsz", argv[i]) == 0){ 00076 fft_size = atoi(argv[++i]); 00077 } 00078 else if(strcmp("-z", argv[i]) == 0){ 00079 n_zernikes = atoi(argv[++i]); 00080 } 00081 else if(strcmp("-r", argv[i]) == 0){ 00082 prange = atoi(argv[++i]); 00083 } 00084 else if(strcmp("-s", argv[i]) == 0){ 00085 n_swarms = atoi(argv[++i]); 00086 } 00087 else if(strcmp("-p", argv[i]) == 0){ 00088 n_particles = atoi(argv[++i]); 00089 } 00090 else if(strcmp("-c", argv[i]) == 0){ 00091 n_cycles = atoi(argv[++i]); 00092 } 00093 else if(strcmp("-w", argv[i]) == 0){ 00094 w = atof(argv[++i]); 00095 } 00096 else if(strcmp("-c1", argv[i]) == 0){ 00097 c1 = atof(argv[++i]); 00098 } 00099 else if(strcmp("-c2", argv[i]) == 0){ 00100 c2 = atof(argv[++i]); 00101 } 00102 else if(strcmp("-reset", argv[i]) == 0){ 00103 reset = atof(argv[++i]); 00104 } 00105 else if(strcmp("-nval", argv[i]) == 0){ 00106 n_validations = atoi(argv[++i]); 00107 } 00108 else if(strcmp("-ranksz", argv[i]) == 0){ 00109 rank_size = atoi(argv[++i]); 00110 } 00111 else if(strcmp("-noise", argv[i]) == 0){ 00112 poisson = atoi(argv[++i]); 00113 } 00114 else if(strcmp("-gen_imgs", argv[i]) == 0){ 00115 gen_images = true; 00116 n_images_gen = atoi(argv[++i]); 00117 } 00118 else if(strcmp("-statistics", argv[i]) == 0){ 00119 statistics = true; 00120 } 00121 else if(strcmp("-devices", argv[i]) == 0){ 00122 char *ptr = strtok (argv[++i], ","); 00123 devices = new vector<int>; 00124 int device; 00125 while(ptr != NULL){ 00126 if ((device = atoi(ptr)) == 0){ 00127 delete devices; 00128 printf("Invalid Device ID!\n"); 00129 show_usage(); 00130 exit(1); 00131 } 00132 devices->push_back(device); 00133 ptr = strtok (NULL, ","); 00134 } 00135 } 00136 else if(strcmp("-validation", argv[i]) == 0){ 00137 PSF_validation = true; 00138 } 00139 else if(strcmp("-parallel", argv[i]) == 0){ 00140 parallel = atoi(argv[++i]); 00141 } 00142 } 00143 // Verify if any parameter is missing. 00144 if(objectname == NULL || image_size <= 0 00145 || (!rms_contrast && !sum && (fft_size <= 0 || n_zernikes <= 0 || poisson < 0 || poisson > 700 || parallel < 1 00146 || (!PSF_validation && !gen_images && (imgpath == NULL || outpath == NULL || n_particles <= 0 || n_swarms <= 0 || n_cycles <= 0 || w <= 0 || c1 <= 0 || c2 <= 0 || reset < 0)) 00147 || (PSF_validation && !gen_images && (n_validations <= 0 || rank_size <= 0)) 00148 || (!PSF_validation && gen_images && n_images_gen <= 0) 00149 || (PSF_validation && gen_images)))){ 00150 cout << "Error on parameters." << endl; 00151 show_usage(); 00152 exit(1); 00153 } 00154 00155 printf("\n\n\n ------------------------------------------------\n"); 00156 printf(" | PSF Estimation Based on CPSO Optimization for GPUs. |\n"); 00157 printf(" ------------------------------------------------\n\n"); 00158 00159 int img_area = image_size * image_size; 00160 if(rms_contrast || sum){ 00161 FitsManager::startup(fitsSize(objectname)); 00162 FitsManager *fitsManager = new FitsManager(1, image_size, image_size, NULL, objectname, NULL); 00163 if(rms_contrast){ 00164 int n_images = fitsManager->size(); 00165 fits_result *result; 00166 for(int i=0; i < n_images; i++){ 00167 if((result = fitsManager->nextImage()) == NULL){ 00168 continue; 00169 } 00170 printf("[%i] RMS contrast = %f\n", i+1, rmsContrast(result->image, image_size)); 00171 } 00172 } 00173 else{ 00174 double sum[img_area]; 00175 sum_3dfits_file(fitsManager, sum, img_area); 00176 ostringstream oss; 00177 oss << objectname << "-3dsum.fits"; 00178 writeFitsFile((char*)oss.str().c_str(), sum, image_size, image_size, 1); 00179 printf("The sum was saved in : %s\n", (char*)oss.str().c_str()); 00180 } 00181 delete fitsManager; 00182 return 0; 00183 } 00184 00185 TimeTracker tracker("Main"); 00186 tracker.start(); 00187 00188 // Set the following parameters based on the telescope characteristics. 00189 //--------------------------------------------------------------------- 00190 double wavelength = 396E-9; 00191 double image_scale = 0.09; 00192 double tel_dia = 0.7; 00193 //--------------------------------------------------------------------- 00194 00195 int size_fft = fft_size * fft_size; 00196 double cut_freq = cmp_freq_cut(tel_dia, image_scale, wavelength, image_size); 00197 int size_phases = cmp_size_of_phase(tel_dia, image_scale, wavelength, fft_size) / 2; 00198 00199 int *phase_mask = new int[size_fft]; 00200 int* diff_mask = new int[img_area]; 00201 double *object = new double[img_area]; 00202 double *radial_values = new double[size_fft]; 00203 double *theta_values = new double[size_fft]; 00204 double *zernikes = new double[n_zernikes * size_fft]; 00205 00206 // compute radial values 00207 gen_radial_values(radial_values, size_phases, fft_size); 00208 00209 // compute angular_values 00210 gen_angular_values(theta_values, fft_size); 00211 00212 // generate mask 00213 gen_circ_mask(phase_mask, size_phases, fft_size / 2, fft_size / 2, fft_size); 00214 00215 // compute zernikes 00216 gen_zernike_values(zernikes, radial_values, theta_values, fft_size, n_zernikes); 00217 norm_zernikes(zernikes, fft_size, n_zernikes); 00218 00219 // create diffraction limit mask 00220 gen_freq_mask(diff_mask, cut_freq, image_size, image_size); 00221 00222 if(PSF_validation || gen_images){ 00223 // Read the Object. 00224 read_fits_file((char*)objectname, object, image_size, image_size); 00225 if(PSF_validation){ 00226 // The validation of this method cannot have the Hamming window applied over the object and the images, 00227 // since it will be using the Object to create random artificial images as base for the PSF estimation method. 00228 // Besides, the use of a window is optional and will interfere with the validation of this estimation method. 00229 validate_psfcode(object, zernikes, diff_mask, n_zernikes, image_size, fft_size, prange, phase_mask, 00230 (char*)objectname, n_validations, rank_size, devices, poisson, parallel); 00231 } 00232 else{ 00233 generate_random_images(object, zernikes, diff_mask, n_zernikes, image_size, fft_size, prange, phase_mask, 00234 (char*)objectname, n_images_gen, devices, poisson, parallel); 00235 } 00236 } 00237 else{ 00238 // Set the buffer size to 2 time the number of threads. 00239 FitsManager::startup(parallel * 2); 00240 FitsManager *fitsManager = new FitsManager(n_zernikes, image_size, fft_size, objectname, imgpath, outpath); 00241 00242 int n_images = fitsManager->size(); 00243 fits_result *result; 00244 00245 // Calculate the Hamming window. 00246 double *hamming = new double[img_area]; 00247 frac_hamming(hamming, 0.3, image_size, image_size); 00248 00249 // Apply the Hamming window over the Object. 00250 apply_window(fitsManager->getObject(), hamming, img_area); 00251 00252 /* CPSO Parameters: 00253 * - w: Never accelerating too much, since the search space is small. Too much speed reduction is also not good. 00254 * - c1: Always more important than c2. A low value affects the convergence (c1<1) and a high value makes it stuck for long periods (c1>1.5). 00255 * - c2: A good value would be c2<=c1, with c2~=c1/2 as usually the best choice. 00256 * - Particle re-initialization factor: usually something between 0.05 and 0.25. 00257 * - No.Particles: More particles is better (eg. 128 or 256), because it means more random starting points. 00258 * However, on GPUs it seems to have better results when equals to the warp size (eg., 32). 00259 * - No.Swarms: 3 swarms has returned much better values and has better convergence behavior than 2 swarms, 00260 * but for 1 swarm or n_swarms>=4 the convergence is often being stuck for much longer periods. 00261 */ 00262 PsfEstimator::startup(parallel, zernikes, phase_mask, diff_mask, fft_size, image_size, n_zernikes, prange, w, c1, c2, reset, n_particles, n_swarms, devices); 00263 00264 double all_costs[n_images], all_times[n_images], all_stable_convergence[n_images]; 00265 00266 omp_set_num_threads(parallel); 00267 #pragma omp parallel for shared(fitsManager, object, zernikes, diff_mask, phase_mask, hamming, all_costs, all_times, all_stable_convergence) \ 00268 firstprivate(n_zernikes, image_size, fft_size, prange, n_images, img_area, size_fft, n_cycles, statistics) \ 00269 private(result) default(none) 00270 for (int i=0; i < n_images; i++) { 00271 if((result = fitsManager->nextImage()) == NULL){ 00272 continue; 00273 } 00274 00275 TimeTracker tracker_estimation("single-estimation"); 00276 if(statistics) tracker_estimation.start(); 00277 00278 // Apply the Hamming window over the Image. 00279 apply_window(result->image, hamming, img_area); 00280 00281 // Load the Object and the Image to the CPSO search mechanism. 00282 CPSO *cpso = PsfEstimator::getCPSO(result->object, result->image); 00283 // Compute the PSF. 00284 run_cpso(cpso, result, n_cycles); 00285 // Save the results. 00286 fitsManager->saveImage(result); 00287 00288 if(statistics){ 00289 tracker_estimation.end(); 00290 all_costs[i] = cpso->getGBestCost(); 00291 all_times[i] = tracker_estimation.elapsedTime(); 00292 all_stable_convergence[i] = cpso->getStableCycle(); 00293 } 00294 00295 printf("File %i\n", i); 00296 00297 cpso->release(); 00298 } 00299 00300 if(statistics){ 00301 cout << "* Statistics for Estimations:" << endl; 00302 cout << "- Time: avg.time=" << CPSO::calc_mean(all_times, n_images) << 00303 ", std.dev.time=" << CPSO::calc_stddev(all_times, n_images) << 00304 ", variance.time=" << CPSO::calc_variance(all_times, n_images) << endl; 00305 cout << "- Fitness: avg.fitness=" << CPSO::calc_mean(all_costs, n_images) << 00306 ", std.dev.fitness=" << CPSO::calc_stddev(all_costs, n_images) << 00307 ", variance.fitness=" << CPSO::calc_variance(all_costs, n_images) << endl; 00308 cout << "- Stabilization: avg.cycle=" << CPSO::calc_mean(all_stable_convergence, n_images) << 00309 ", std.dev.cycle=" << CPSO::calc_stddev(all_stable_convergence, n_images) << 00310 ", variance.cycle=" << CPSO::calc_variance(all_stable_convergence, n_images) << endl; 00311 } 00312 00313 delete fitsManager; 00314 delete hamming; 00315 } 00316 00317 // Free up the memory. 00318 delete zernikes; 00319 delete object; 00320 delete theta_values; 00321 delete radial_values; 00322 delete diff_mask; 00323 delete phase_mask; 00324 if(devices != NULL){ 00325 delete devices; 00326 } 00327 00328 PsfEstimator::shutdown(); 00329 00330 #ifdef _PROFILING_ 00331 cout << "Total OpenCL Time (miliseconds): " << Profiling::getTotalProcessingTime() << endl; 00332 #endif 00333 00334 tracker.end(); 00335 printf("Total time...\n"); 00336 tracker.print(); 00337 00338 return 0; 00339 } 00340 00344 void show_usage(){ 00345 cout << "Usage: kippe [-h] | [-testgpu] | [-listgpu] |" << endl 00346 << " [-rms_contrast -obj <image> -isz <image_width>] |" << endl 00347 << " [-sum -obj <image> -isz <image_width>] |" << endl 00348 << " [-obj <object> -isz <image_width> -fsz <fft_width> -z <num_zernikes>" << endl 00349 << " [[-img <image> -out <output_path> -s <num_swarms> -p <num_particles>" << endl 00350 << " -c <num_cycles> -w <w_val> -c1 <c1_val> -c2 <c2_val> -reset <reset_factor>] |" << endl 00351 << " [-validation -nval <num_validations> -ranksz <rank_size> {-noise <noise-level>}] |" << endl 00352 << " [-gen_imgs <num_artificial_images>]]" << endl 00353 << " {-r <coef_range>} {-fixedrand} {-statistics} {-devices <device_id_to_use>}" << endl 00354 << " {-parallel <n_threads>}]" << endl 00355 << "where: " << endl 00356 << "\t-h This help message." << endl 00357 << "\t-testgpu Test all GPUs available." << endl 00358 << "\t-listgpu Get the list of device ids available on the system." << endl 00359 << "\t-sum Sum a 3D FITS file and generate a 2D FITS file as output." << endl 00360 << "\t-rms_contrast Calculate the image intensity." << endl 00361 << "\t-obj The path to the FITS file containing the Object." << endl 00362 << "\t-img The path to either a FITS file containing a 2D/3D Image" << endl 00363 << "\t or the path to a folder containing multiple 2D Image files." << endl 00364 << "\t-out The output folder where the data will be saved." << endl 00365 << "\t-isz The widh of the input image." << endl 00366 << "\t-fsz The width of the FFT to be calculated." << endl 00367 << "\t-z The number of Zernikes to be calculated." << endl 00368 << "\t-r The range for the Zernike coefficients. If not provided, the value 2 will be used." << endl 00369 << "\t-s The number of swarms to be created." << endl 00370 << "\t-p The number of particles to be used on every swarm." << endl 00371 << "\t-c The number of cycles to run the CPSO." << endl 00372 << "\t-w The Inertia weight W." << endl 00373 << "\t-c1 The Acceleration coefficient C1 (cognitive)." << endl 00374 << "\t-c2 The Acceleration coefficient C2 (social)." << endl 00375 << "\t-reset The factor for re-initialization of inactive particles [0-1]." << endl 00376 << "\t-validation If provided, the tool will run on Validation mode." << endl 00377 << "\t-nval The number of validations to be executed." << endl 00378 << "\t-ranksz The rank size to store the best and worst values." << endl 00379 << "\t-noise The Poisson noise level to be added to the artificial image: 0 (default), 1, .. 700." << endl 00380 << "\t-gen_imgs If provided, the tool will run on Generation Images mode." << endl 00381 << "\t Specify the number of artificial images to be generated in the 3D output FITS file." << endl 00382 << "\t-fixedrand If provided, the Random Number Generator seed will be fixed at program startup." << endl 00383 << "\t-statistics If provided, the statistics will be printed on standard output." << endl 00384 << "\t-devices The list of device ids (separated by comma and no space) that should be used." << endl 00385 << "\t To get the list of device ids, run the program with the option -listgpu." << endl 00386 << "\t-parallel Define the number of threads to be used. For basic image processing, it is also" << endl 00387 << "\t the number of CPSO's to be executed in parallel. The default is 1 thread." << endl; 00388 }