69 const Eigen::DenseBase<Derived> &limits) {
74 Eigen::Map<const typename Model::InputDataType> _x(xy_data.data(), xy_data.rows(), xy_data.cols());
75 Eigen::Map<const typename Fitter::ValueType> _y(z_data.data(), z_data.size());
76 Eigen::Map<const typename Fitter::ValueType> _s(sigma.data(), sigma.size());
84 CostFunction* cost_function =
85 new AutoDiffCostFunction<Fitter, Fitter::ValuesAtCompileTime, Fitter::InputsAtCompileTime>(fitter, fitter->values());
88 Eigen::VectorXd params(init_params);
89 auto problem = fitter->createProblem(params.data());
92 problem->AddResidualBlock(cost_function,
nullptr, params.data());
96 for (
int i=0; i<limits.rows(); ++i) {
97 problem->SetParameterLowerBound(params.data(), i, limits(i,0));
98 problem->SetParameterUpperBound(params.data(), i, limits(i,1));
103 std::vector<int> sspv;
104 sspv.push_back(limits.rows()-1);
106 if (sspv.size() > 0 ){
107 ceres::SubsetParameterization *pcssp
108 =
new ceres::SubsetParameterization(limits.rows(), sspv);
109 problem->SetParameterization(params.data(), pcssp);
114 Solver::Options options;
116 options.linear_solver_type = ceres::LinearSolverType::DENSE_QR;
118 options.logging_type = ceres::LoggingType::SILENT;
120 options.minimizer_progress_to_stdout =
false;
122 Solver::Summary summary;
124 Solve(options, problem.get(), &summary);
127 Eigen::VectorXd uncertainty(params.size());
130 if (summary.IsSolutionUsable()) {
132 Covariance::Options covariance_options;
134 covariance_options.sparse_linear_algebra_library_type = ceres::SparseLinearAlgebraLibraryType::EIGEN_SPARSE;
135 covariance_options.algorithm_type = ceres::CovarianceAlgorithmType::DENSE_SVD;
137 covariance_options.null_space_rank = -1;
139 Covariance covariance(covariance_options);
142 std::vector<std::pair<const double*, const double*>> covariance_blocks;
144 covariance_blocks.push_back(std::make_pair(params.data(), params.data()));
146 auto covariance_result = covariance.Compute(covariance_blocks, problem.get());
149 if (covariance_result) {
151 Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> covariance_matrix;
152 covariance_matrix.resize(params.size(),params.size());
153 covariance.GetCovarianceBlock(params.data(),params.data(),covariance_matrix.data());
155 uncertainty = covariance_matrix.diagonal().cwiseSqrt();
159 uncertainty.setConstant(0);
164 params.setConstant(0);
165 uncertainty.setConstant(0);
168 return std::tuple<Eigen::VectorXd, Eigen::VectorXd,bool>(params,uncertainty,summary.IsSolutionUsable());
173 double init_fwhm,
double init_row,
double init_col) {
176 Eigen::VectorXd init_params(
n_params);
180 double init_flux = 0;
186 if (init_row<0 && init_col<0) {
188 double center_row = (signal.rows() - 1)/2;
189 double center_col = (signal.cols() - 1)/2;
192 auto sig2noise = signal.derived().array()*sqrt(weight.derived().array());
198 sig2noise.maxCoeff(&ir, &ic);
199 init_flux = signal(ir,ic);
203 for (Eigen::Index i=0; i<sig2noise.rows(); ++i) {
204 for (Eigen::Index j=0; j<sig2noise.cols(); ++j) {
205 auto dist = sqrt(pow(i - center_row,2) + pow(j - center_col,2));
207 if (sig2noise(i,j) > init_flux) {
208 init_flux = sig2noise(i,j);
216 init_flux = signal(ir, ic);
224 init_flux = signal(
static_cast<int>(init_row),
static_cast<int>(init_col));
228 init_params << init_flux, init_col, init_row, init_sigma, init_sigma, 0;
231 double lower_row, lower_col, upper_row, upper_col;
238 upper_row = signal.rows() - 1;
239 upper_col = signal.cols() - 1;
248 upper_row = std::min(init_row +
bounding_box_pix,
static_cast<double>(signal.rows()) - 1);
249 upper_col = std::min(init_col +
bounding_box_pix,
static_cast<double>(signal.cols()) - 1);
253 double n_rows = upper_row - lower_row + 1;
254 double n_cols = upper_col - lower_col + 1;
257 limits.col(0) <<
flux_low*init_flux, lower_col, lower_row,
fwhm_low*init_sigma,
264 Eigen::VectorXd x, y;
267 x = Eigen::VectorXd::LinSpaced(n_cols, lower_col, upper_col);
268 y = Eigen::VectorXd::LinSpaced(n_rows, lower_row, upper_row);
271 auto g = create_model<Gaussian2D>(init_params);
273 auto xy = g.meshgrid(x, y);
279 Eigen::MatrixXd sigma(weight.rows(), weight.cols());
282 for (Eigen::Index i=0; i<weight.rows(); ++i) {
283 for (Eigen::Index j=0; j<weight.cols(); ++j) {
284 if (weight(i,j)!=0) {
287 sigma(i,j) = map_sigma;
291 sigma(i,j) = 1./sqrt(weight(i,j));
301 Eigen::MatrixXd _signal = signal.block(lower_row, lower_col, n_rows, n_cols);
302 Eigen::MatrixXd _sigma = sigma.block(lower_row, lower_col, n_rows, n_cols);
305 return ceres_fit(g, init_params, xy, _signal, _sigma, limits);