int main(int argc, char *argv[]) { int nPixels_tot, nColumns, nRows; int nPixels_psf, nRows_psf, nColumns_psf; int nParamsTot; int status; double *psfPixels; double *paramsVect; ModelObject *theModel; vector<string> functionList; vector<double> parameterList; vector<int> functionBlockIndices; commandOptions options; configOptions userConfigOptions; // timing-related stuff struct timeval timer_start, timer_end; double microsecs, time_elapsed; /* Process command line and parse config file: */ options.outputImageName = DEFAULT_OUTPUT_FILENAME; options.noImageName = true; options.noRefImage = true; options.subsamplingFlag = true; options.noImageDimensions = true; options.referenceImageName = ""; options.psfImagePresent = false; options.psfFileName = ""; options.nColumns = 0; options.nRows = 0; options.noConfigFile = true; options.configFileName = ""; options.noModel = true; options.noParamLimits = true; options.magZeroPoint = NO_MAGNITUDES; options.printImages = false; options.nIterations = 1; options.debugLevel = 0; ProcessInput(argc, argv, &options); /* Read configuration file */ if (! FileExists(options.configFileName.c_str())) { fprintf(stderr, "\n*** ERROR: Unable to find configuration file \"%s\"!\n\n", options.configFileName.c_str()); return -1; } status = ReadConfigFile(options.configFileName, true, functionList, parameterList, functionBlockIndices, userConfigOptions); if (status != 0) { fprintf(stderr, "\n*** ERROR: Failure reading configuration file \"%s\"!\n\n", options.configFileName.c_str()); return -1; } if ((options.noRefImage) and (options.noImageDimensions)) { fprintf(stderr, "\n*** ERROR: Insufficient image dimensions (or no reference image) supplied!\n\n"); return -1; } /* Get image size from reference image, if necessary */ if (options.noImageDimensions) { status = GetImageSize(options.referenceImageName, &nColumns, &nRows); if (status != 0) { fprintf(stderr, "\n*** ERROR: Failure determining size of image file \"%s\"!\n\n", options.referenceImageName.c_str()); exit(-1); } // Reminder: nColumns = n_pixels_per_row // Reminder: nRows = n_pixels_per_column printf("Reference image read: naxis1 [# rows] = %d, naxis2 [# columns] = %d\n", nRows, nColumns); } else { nColumns = options.nColumns; nRows = options.nRows; } nPixels_tot = nColumns * nRows; /* Read in PSF image, if supplied */ if (options.psfImagePresent) { printf("Reading PSF image (\"%s\") ...\n", options.psfFileName.c_str()); psfPixels = ReadImageAsVector(options.psfFileName, &nColumns_psf, &nRows_psf); if (psfPixels == NULL) { fprintf(stderr, "\n*** ERROR: Unable to read PSF image file \"%s\"!\n\n", options.psfFileName.c_str()); exit(-1); } nPixels_psf = nColumns_psf * nRows_psf; printf("naxis1 [# pixels/row] = %d, naxis2 [# pixels/col] = %d; nPixels_tot = %d\n", nColumns_psf, nRows_psf, nPixels_psf); } else printf("* No PSF image supplied -- no image convolution will be done!\n"); if (! options.subsamplingFlag) printf("* Pixel subsampling has been turned OFF.\n"); /* Set up the model object */ theModel = new ModelObject(); theModel->SetDebugLevel(options.debugLevel); /* Add functions to the model object; also tells model object where function sets start */ status = AddFunctions(theModel, functionList, functionBlockIndices, options.subsamplingFlag); if (status < 0) { fprintf(stderr, "*** ERROR: Failure in AddFunctions!\n\n"); exit(-1); } // Add PSF image vector, if present (needs to be added prior to image data, so that // ModelObject can figure out proper internal model-image size if (options.psfImagePresent) { status = theModel->AddPSFVector(nPixels_psf, nColumns_psf, nRows_psf, psfPixels); if (status < 0) { fprintf(stderr, "*** ERROR: Failure in ModelObject::AddPSFVector!\n\n"); exit(-1); } } /* Define the size of the requested model image */ theModel->SetupModelImage(nColumns, nRows); theModel->PrintDescription(); // Set up parameter vector(s), now that we know how many total parameters // there will be nParamsTot = theModel->GetNParams(); printf("%d total parameters\n", nParamsTot); if (nParamsTot != (int)parameterList.size()) { fprintf(stderr, "*** ERROR: number of input parameters (%d) does not equal", (int)parameterList.size()); fprintf(stderr, " required number of parameters for specified functions (%d)!\n\n", nParamsTot); exit(-1); } /* Copy parameters into C array and generate the model image */ paramsVect = (double *) calloc(nParamsTot, sizeof(double)); for (int i = 0; i < nParamsTot; i++) paramsVect[i] = parameterList[i]; // Generate the image (including convolution, if requested), repeatedly gettimeofday(&timer_start, NULL); for (int ii = 0; ii < options.nIterations; ii++) theModel->CreateModelImage(paramsVect); gettimeofday(&timer_end, NULL); microsecs = timer_end.tv_usec - timer_start.tv_usec; time_elapsed = timer_end.tv_sec - timer_start.tv_sec + microsecs/1e6; printf("\nELAPSED TIME FOR %d ITERATIONS: %.6f sec\n", options.nIterations, time_elapsed); printf("Mean time per iteration = %.7f\n", time_elapsed/options.nIterations); /* Save model image: */ printf("\nSaving output model image (\"%s\") ...\n", options.outputImageName.c_str()); vector<string> commentStrings; SaveVectorAsImage(theModel->GetModelImageVector(), options.outputImageName, nColumns, nRows, commentStrings); printf("Done!\n\n"); // Free up memory if (options.psfImagePresent) free(psfPixels); free(paramsVect); delete theModel; return 0; }
int main(int argc, char *argv[]) { int nDataVals, nStoredDataVals, nSavedRows; int nPixels_psf; int startDataRow, endDataRow; int nParamsTot, nFreeParams; int nDegFreedom; double *xVals, *yVals, *yWeights, *maskVals; double *xVals_psf, *yVals_psf; int weightMode = WEIGHTS_ARE_SIGMAS; FILE *outputFile_ptr; ModelObject *theModel; double *paramsVect; double *paramErrs; vector<mp_par> paramLimits; vector<int> FunctionBlockIndices; bool maskAllocated = false; bool paramLimitsExist = false; vector<mp_par> parameterInfo; int status, fitStatus; vector<string> functionList; vector<double> parameterList; commandOptions options; configOptions userConfigOptions; SolverResults resultsFromSolver; string nloptSolverName; vector<string> programHeader; string progNameVersion = "profilefit "; /* PROCESS COMMAND-LINE: */ /* First, set up the options structure: */ options.configFileName = DEFAULT_CONFIG_FILE; options.dataFileName = ""; options.modelOutputFileName = DEFAULT_MODEL_OUTPUT_FILE; options.noDataFile = true; options.noConfigFile = true; options.psfPresent = false; options.dataAreMagnitudes = true; // default: assumes we usually fit mu(R) profiles options.zeroPoint = 0.0; options.startDataRow = 0; options.endDataRow = -1; // default value indicating "last row in data file" options.noErrors = true; options.noMask = true; options.maskFormat = MASK_ZERO_IS_GOOD; options.ftol = DEFAULT_FTOL; options.ftolSet = false; options.printChiSquaredOnly = false; options.solver = MPFIT_SOLVER; options.nloptSolverName = "NM"; // default value = Nelder-Mead Simplex options.doBootstrap = false; options.bootstrapIterations = 0; options.subsamplingFlag = false; options.saveBestProfile = false; options.saveBestFitParams = true; options.outputParameterFileName = DEFAULT_1D_OUTPUT_PARAMETER_FILE; options.verbose = 1; options.nloptSolverName = ""; options.rngSeed = 0; progNameVersion += VERSION_STRING; MakeOutputHeader(&programHeader, progNameVersion, argc, argv); ProcessInput(argc, argv, &options); if (options.noDataFile) { printf("*** WARNING: No data to fit!\n\n"); return -1; } /* Read configuration file */ if (! FileExists(options.configFileName.c_str())) { printf("\n*** WARNING: Unable to find or open configuration file \"%s\"!\n\n", options.configFileName.c_str()); return -1; } status = ReadConfigFile(options.configFileName, false, functionList, parameterList, paramLimits, FunctionBlockIndices, paramLimitsExist, userConfigOptions); if (status < 0) { printf("\n*** WARNING: Problem in processing config file!\n\n"); return -1; } /* GET THE DATA: */ nDataVals = CountDataLines(options.dataFileName); if ((nDataVals < 1) || (nDataVals > MAX_N_DATA_VALS)) { /* file has no data *or* too much data (or an integer overflow occured in CountDataLines) */ printf("Something wrong: input file %s has too few or too many data points\n", options.dataFileName.c_str()); printf("(nDataVals = %d)\n", nDataVals); exit(1); } printf("Data file \"%s\": %d data points\n", options.dataFileName.c_str(), nDataVals); /* Set default end data row (if not specified) and check for reasonable values: */ startDataRow = options.startDataRow; endDataRow = options.endDataRow; if (endDataRow == -1) endDataRow = nDataVals - 1; if ( (startDataRow < 0) || (startDataRow >= nDataVals) ) { printf("Starting data row (\"--x1\") must be >= 1 and <= number of rows in data file (%d)!\n", nDataVals); exit(-1); } if ( (endDataRow <= startDataRow) || (endDataRow >= nDataVals) ) { printf("Ending data row (\"--x2\") must be >= starting data row and <= number of rows in data file (%d)!\n", nDataVals); exit(-1); } /* Allocate data vectors: */ nStoredDataVals = endDataRow - startDataRow + 1; xVals = (double *)calloc( (size_t)nStoredDataVals, sizeof(double) ); yVals = (double *)calloc( (size_t)nStoredDataVals, sizeof(double) ); if ( (xVals == NULL) || (yVals == NULL) ) { fprintf(stderr, "\nFailure to allocate memory for input data!\n"); exit(-1); } if (options.noErrors) yWeights = NULL; else yWeights = (double *)calloc( (size_t)nStoredDataVals, sizeof(double) ); if (options.noMask) maskVals = NULL; else { maskVals = (double *)calloc( (size_t)nStoredDataVals, sizeof(double) ); maskAllocated = true; } /* Read in data */ nSavedRows = ReadDataFile(options.dataFileName, startDataRow, endDataRow, xVals, yVals, yWeights, maskVals); if (nSavedRows > nStoredDataVals) { fprintf(stderr, "\nMore data rows saved (%d) than we allocated space for (%d)!\n", nSavedRows, nStoredDataVals); exit(-1); } if (options.noErrors) { // OK, we previously had yWeights = NULL to tell ReadDataFile() to skip // the third column (if any); now we need to have a yWeights vector with // all weights = 1.0 yWeights = (double *)calloc( (size_t)nStoredDataVals, sizeof(double) ); for (int i = 0; i < nStoredDataVals; i++) yWeights[i] = 1.0; } /* Read in PSF profile, if supplied */ if (options.psfPresent) { nPixels_psf = CountDataLines(options.psfFileName); if ((nPixels_psf < 1) || (nPixels_psf > MAX_N_DATA_VALS)) { /* file has no data *or* too much data (or an integer overflow occured in CountDataLines) */ printf("Something wrong: input PSF file %s has too few or too many data points\n", options.psfFileName.c_str()); printf("(nPixels_psf (# of PSF points) = %d)\n", nPixels_psf); exit(1); } printf("PSF file \"%s\": %d data points\n", options.psfFileName.c_str(), nPixels_psf); /* Set default end data row (if not specified) and check for reasonable values: */ startDataRow = 0; endDataRow = nPixels_psf - 1; xVals_psf = (double *)calloc( (size_t)nPixels_psf, sizeof(double) ); yVals_psf = (double *)calloc( (size_t)nPixels_psf, sizeof(double) ); if ( (xVals_psf == NULL) || (yVals_psf == NULL) ) { fprintf(stderr, "\nFailure to allocate memory for PSF data!\n"); exit(-1); } nSavedRows = ReadDataFile(options.psfFileName, startDataRow, endDataRow, xVals_psf, yVals_psf, NULL, NULL); if (nSavedRows > nStoredDataVals) { fprintf(stderr, "\nMore PSF rows saved (%d) than we allocated space for (%d)!\n", nSavedRows, nPixels_psf); exit(-1); } } /* Set up the model object */ theModel = new ModelObject1d(); /* Add functions to the model object */ printf("Adding functions to model object...\n"); status = AddFunctions1d(theModel, functionList, FunctionBlockIndices); if (status < 0) { printf("*** WARNING: Failure in AddFunctions!\n\n"); exit(-1); } theModel->SetZeroPoint(options.zeroPoint); // Set up parameter vector(s), now that we know how many total parameters // there will be nParamsTot = nFreeParams = theModel->GetNParams(); printf("\t%d total parameters\n", nParamsTot); paramsVect = (double *) malloc(nParamsTot * sizeof(double)); for (int i = 0; i < nParamsTot; i++) paramsVect[i] = parameterList[i]; paramErrs = (double *) malloc(nParamsTot * sizeof(double)); /* Add image data, errors, and mask to the model object */ // "true" = input yVals data are magnitudes, not intensities theModel->AddDataVectors(nStoredDataVals, xVals, yVals, options.dataAreMagnitudes); theModel->AddErrorVector1D(nStoredDataVals, yWeights, WEIGHTS_ARE_SIGMAS); if (maskAllocated) { status = theModel->AddMaskVector1D(nStoredDataVals, maskVals, options.maskFormat); if (status < 0) { fprintf(stderr, "*** ERROR: Failure in ModelObject::AddMaskVector1D!\n\n"); exit(-1); } } // Add PSF vector, if present, and thereby enable convolution if (options.psfPresent) { status = theModel->AddPSFVector1D(nPixels_psf, xVals_psf, yVals_psf); if (status < 0) { fprintf(stderr, "*** ERROR: Failure in ModelObject::AddPSFVector1D!\n\n"); exit(-1); } } theModel->FinalSetupForFitting(); // calls ApplyMask(), VetDataVector() theModel->PrintDescription(); // Parameter limits and other info: printf("Setting up parameter information vector ...\n"); mp_par newParamLimit; for (int i = 0; i < nParamsTot; i++) { memset(&newParamLimit, 0, sizeof(mp_par)); newParamLimit.fixed = paramLimits[i].fixed; if (paramLimits[i].fixed == 1) { printf("Fixed parameter detected (i = %d)\n", i); nFreeParams--; } newParamLimit.limited[0] = paramLimits[i].limited[0]; newParamLimit.limited[1] = paramLimits[i].limited[1]; newParamLimit.limits[0] = paramLimits[i].limits[0]; newParamLimit.limits[1] = paramLimits[i].limits[1]; parameterInfo.push_back(newParamLimit); } nDegFreedom = theModel->GetNValidPixels() - nFreeParams; printf("%d free parameters (%d degrees of freedom)\n", nFreeParams, nDegFreedom); // tell ModelObject about parameterInfo (mainly useful for printing-related methods) theModel->AddParameterInfo(parameterInfo); // OK, now we either print chi^2 value for the input parameters and quit, or // else call one of the solvers! if (options.printChiSquaredOnly) { printf("\n"); fitStatus = 1; PrintFitStatistic(paramsVect, theModel, nFreeParams); printf("\n"); // turn off saveing of parameter file options.saveBestFitParams = false; } else { // DO THE FIT! fitStatus = DispatchToSolver(options.solver, nParamsTot, nFreeParams, nStoredDataVals, paramsVect, parameterInfo, theModel, options.ftol, paramLimitsExist, options.verbose, &resultsFromSolver, options.nloptSolverName, options.rngSeed); PrintResults(paramsVect, theModel, nFreeParams, fitStatus, resultsFromSolver); } // OPTIONAL HANDLING OF BOOTSTRAP RESAMPLING HERE if ((options.doBootstrap) && (options.bootstrapIterations > 0)) { printf("\nNow doing bootstrap resampling (%d iterations) to estimate errors...\n", options.bootstrapIterations); printf("[NOT YET PROPERLY IMPLEMENTED!]\n"); BootstrapErrors(paramsVect, parameterInfo, paramLimitsExist, theModel, options.ftol, options.bootstrapIterations, nFreeParams); } if (options.saveBestFitParams) { printf("Saving best-fit parameters in file \"%s\"\n", options.outputParameterFileName.c_str()); string progNameVer = "profilefit "; progNameVer += VERSION_STRING; SaveParameters(paramsVect, theModel, options.outputParameterFileName, programHeader, nFreeParams, options.solver, fitStatus, resultsFromSolver); } if (options.saveBestProfile) { theModel->CreateModelImage(paramsVect); double *modelProfile = (double *) calloc((size_t)nStoredDataVals, sizeof(double)); int nPts = theModel->GetModelVector(modelProfile); if (nPts == nStoredDataVals) { printf("Saving model profile to %s...\n", options.modelOutputFileName.c_str()); outputFile_ptr = fopen(options.modelOutputFileName.c_str(), "w"); for (int i = 0; i < nPts; i++) { fprintf(outputFile_ptr, "\t%f\t%f\n", xVals[i], modelProfile[i]); } fclose(outputFile_ptr); printf("Done.\n"); } else { printf("WARNING -- MISMATCH BETWEEN nStoredDataVals (main) and nDataVals (ModelObject1d)!\n"); printf("NO PROFILE SAVED!\n"); } free(modelProfile); } // Free up memory free(xVals); free(yVals); free(yWeights); if (maskAllocated) free(maskVals); if (options.psfPresent) { free(xVals_psf); free(yVals_psf); } free(paramsVect); free(paramErrs); delete theModel; printf("All done!\n\n"); return 0; }