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