PSFEstimationwithCPSO
kippe.cpp
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 }
 All Classes Functions