45using namespace ModelFitting;
50 unsigned int max_iterations,
double modified_chi_squared_scale,
56 double deblend_factor,
57 double meta_iteration_stop,
73 if (fitting_rect.getWidth() <= 0 || fitting_rect.getHeight() <= 0) {
76 const auto& frame_info = source.
getProperty<MeasurementFrameInfo>(frame_index);
78 auto min = fitting_rect.getTopLeft();
79 auto max = fitting_rect.getBottomRight();
82 PixelCoordinate border = (
max -
min) * .8 + PixelCoordinate(2, 2);
93 return PixelRectangle(
min,
max);
98 auto stamp_rect = getFittingRect(source, frame_index);
99 return stamp_rect.getWidth() > 0 && stamp_rect.getHeight() > 0;
104 auto rect = getFittingRect(source, frame_index);
107 LayerSubtractedImage, rect.getTopLeft().m_x, rect.getTopLeft().m_y, rect.getWidth(), rect.getHeight()));
119 SeFloat gain = frame_info.getGain();
120 SeFloat saturation = frame_info.getSaturation();
122 auto rect = getFittingRect(source, frame_index);
125 for (
int y = 0;
y < rect.getHeight();
y++) {
126 for (
int x = 0;
x < rect.getWidth();
x++) {
127 auto back_var = variance_map->getValue(rect.getTopLeft().m_x + x, rect.getTopLeft().m_y + y);
128 auto pixel_val = frame_image->getValue(rect.getTopLeft().m_x + x, rect.getTopLeft().m_y + y);
129 if (saturation > 0 && pixel_val > saturation) {
130 weight->at(x, y) = 0;
132 else if (gain > 0.0 && pixel_val > 0.0) {
133 weight->at(x, y) =
sqrt(1.0 / (back_var + pixel_val / gain));
136 weight->at(x, y) =
sqrt(1.0 / back_var);
149 int frame_index = frame->getFrameNb();
155 auto jacobian = source.getProperty<
JacobianSource>(frame_index).asTuple();
161 auto source_psf =
DownSampledImagePsf(psf_property.getPixelSampling(), psf_property.getPsf(), down_scaling);
167 double model_size =
std::max(stamp_rect.getWidth(), stamp_rect.getHeight());
168 for (
auto model : frame->getModels()) {
169 model->addForSource(manager, source, constant_models, point_models, extended_models, model_size,
170 jacobian, ref_coordinates, frame_coordinates, stamp_rect.getTopLeft());
175 pixel_scale, (
size_t) stamp_rect.getWidth(), (
size_t) stamp_rect.getHeight(),
187 for (
auto& source : group) {
197 if (free_parameter !=
nullptr) {
199 initial_state.
parameters_values[free_parameter->getId()] = free_parameter->getInitialValue(source);
210 int frame_index = frame->getFrameNb();
212 if (isFrameValid(source, frame_index)) {
213 auto stamp_rect = getFittingRect(source, frame_index);
229 double prev_chi_squared = 999999.9;
232 for (
auto& source : group) {
233 fitSource(group, source, index, fitting_state);
239 double chi_squared = 0.0;
241 chi_squared += source_state.reduced_chi_squared;
249 prev_chi_squared = chi_squared;
255 for (
size_t index = 0; index < group.
size(); index++){
261 if (free_parameter !=
nullptr && !source_state.parameters_fitted[parameter->getId()]) {
270 for (
auto& source : group) {
273 int meta_iterations = source_state.chi_squared_per_meta.size();
278 source_state.reduced_chi_squared, source_state.duration, source_state.flags,
279 source_state.parameters_values, source_state.parameters_sigmas,
280 source_state.chi_squared_per_meta, source_state.iterations_per_meta,
281 meta_iterations, source_state.fitting_areas_x, source_state.fitting_areas_y);
293 int frame_index = frame->getFrameNb();
294 auto rect = getFittingRect(source, frame_index);
299 int n_free_parameters = 0;
302 for (
auto& src : group) {
303 if (index != source_index) {
307 if (free_parameter !=
nullptr) {
312 free_parameter->create(parameter_manager, engine_parameter_manager, src,
313 state.
source_states[index].parameters_initial_values.at(free_parameter->getId()),
314 state.
source_states[index].parameters_values.at(free_parameter->getId())));
318 parameter->create(parameter_manager, engine_parameter_manager, src));
327 for (
auto& src : group) {
328 if (index != source_index) {
329 auto frame_model = createFrameModel(src,
pixel_scale, parameter_manager, frame, rect);
330 auto final_stamp = frame_model.getImage();
332 for (
int y = 0; y < final_stamp->getHeight(); ++y) {
333 for (
int x = 0; x < final_stamp->getWidth(); ++x) {
334 deblend_image->at(x, y) += final_stamp->at(x, y);
341 return deblend_image;
348 int free_parameters_nb = 0;
352 if (free_parameter !=
nullptr) {
353 ++free_parameters_nb;
357 free_parameter->create(parameter_manager, engine_parameter_manager, source,
358 state.
source_states[index].parameters_initial_values.at(free_parameter->getId()),
359 state.
source_states[index].parameters_values.at(free_parameter->getId())));
362 parameter->create(parameter_manager, engine_parameter_manager, source));
370 return free_parameters_nb;
379 int valid_frames = 0;
381 int frame_index = frame->getFrameNb();
383 if (isFrameValid(source, frame_index)) {
386 auto stamp_rect = getFittingRect(source, frame_index);
387 auto frame_model = createFrameModel(source,
pixel_scale, parameter_manager, frame, stamp_rect, down_scaling);
389 auto image = createImageCopy(source, frame_index);
392 for (
int y = 0; y < image->getHeight(); ++y) {
393 for (
int x = 0; x < image->getWidth(); ++x) {
398 auto weight = createWeightImage(source, frame_index);
401 for (
int y = 0; y < weight->getHeight(); ++y) {
402 for (
int x = 0; x < weight->getWidth(); ++x) {
403 good_pixels += (weight->at(x, y) != 0.);
424 int total_data_points = 0;
427 int nb_of_free_parameters = 0;
430 bool accessed_by_modelfitting = parameter_manager.
isParamAccessed(source, parameter);
431 if (is_free_parameter && accessed_by_modelfitting) {
432 nb_of_free_parameters++;
435 avg_reduced_chi_squared /= (total_data_points - nb_of_free_parameters);
437 return avg_reduced_chi_squared;
442 SeFloat avg_reduced_chi_squared,
SeFloat duration,
unsigned int iterations,
unsigned int stop_reason,
Flags flags,
453 bool accessed_by_modelfitting = parameter_manager.
isParamAccessed(source, parameter);
454 auto modelfitting_parameter = parameter_manager.
getParameter(source, parameter);
456 if (is_constant_parameter || is_dependent_parameter || accessed_by_modelfitting) {
457 parameters_values[parameter->getId()] = modelfitting_parameter->getValue();
458 parameters_sigmas[parameter->getId()] = parameter->getSigma(parameter_manager, source, solution.
parameter_sigmas);
459 parameters_fitted[parameter->getId()] =
true;
461 parameters_values[parameter->getId()] = state.
source_states[index].parameters_values[parameter->getId()];
462 parameters_sigmas[parameter->getId()] = state.
source_states[index].parameters_sigmas[parameter->getId()];
463 parameters_fitted[parameter->getId()] =
false;
467 if (engine_parameter) {
475 state.
source_states[index].parameters_values = parameters_values;
476 state.
source_states[index].parameters_sigmas = parameters_sigmas;
477 state.
source_states[index].parameters_fitted = parameters_fitted;
478 state.
source_states[index].reduced_chi_squared = avg_reduced_chi_squared;
479 state.
source_states[index].chi_squared_per_meta.emplace_back(avg_reduced_chi_squared);
482 state.
source_states[index].iterations_per_meta.emplace_back(iterations);
494 int frame_index = frame->getFrameNb();
496 if (isFrameValid(source, frame_index)) {
498 auto stamp_rect = getFittingRect(source, frame_index);
499 fit_size =
std::max(fit_size, stamp_rect.getWidth() * stamp_rect.getHeight() /
500 (psf_property.getPixelSampling() * psf_property.getPixelSampling()));
508 <<
" scaling factor: " << down_scaling;
517 parameter_manager, engine_parameter_manager, source, index, state);
522 int n_good_pixels = 0;
524 parameter_manager, res_estimator, n_good_pixels, group, source, index, state, down_scaling);
531 if (valid_frames == 0) {
534 else if (n_good_pixels < n_free_parameters) {
543 if (down_scaling < 1.0) {
551 prior->setupPrior(parameter_manager, source, res_estimator);
558 auto solution = engine->solveProblem(engine_parameter_manager, res_estimator);
560 auto iterations = solution.iteration_no;
561 auto stop_reason = solution.engine_stop_reason;
565 auto duration = solution.duration;
574 fitSourceUpdateState(parameter_manager, source, avg_reduced_chi_squared, duration, iterations, stop_reason, flags, solution,
587 for (
auto& src : group) {
591 if (free_parameter !=
nullptr) {
594 free_parameter->create(parameter_manager, engine_parameter_manager, src,
595 state.
source_states[index].parameters_initial_values.at(free_parameter->getId()),
596 state.
source_states[index].parameters_values.at(free_parameter->getId())));
599 parameter->create(parameter_manager, engine_parameter_manager, src));
605 for (
auto& src : group) {
607 int frame_index = frame->getFrameNb();
609 if (isFrameValid(src, frame_index)) {
610 auto stamp_rect = getFittingRect(src, frame_index);
612 auto frame_model = createFrameModel(src,
pixel_scale, parameter_manager, frame, stamp_rect);
613 auto final_stamp = frame_model.getImage();
618 for (
int x = 0; x < final_stamp->getWidth(); x++) {
619 for (
int y = 0; y < final_stamp->getHeight(); y++) {
620 auto x_coord = stamp_rect.getTopLeft().m_x + x;
621 auto y_coord = stamp_rect.getTopLeft().m_y + y;
622 debug_image->setValue(x_coord, y_coord,
623 debugAccessor.
getValue(x_coord, y_coord) + final_stamp->getValue(x, y));
635 double reduced_chi_squared = 0.0;
641 for (
int y=0; y < image->getHeight(); y++) {
642 for (
int x=0; x < image->getWidth(); x++) {
643 double tmp = imageAccessor.getValue(x, y) - modelAccessor.
getValue(x, y);
644 reduced_chi_squared += tmp * tmp * weightAccessor.
getValue(x, y) * weightAccessor.
getValue(x, y);
645 if (weightAccessor.
getValue(x, y) > 0) {
650 return reduced_chi_squared;
656 total_data_points = 0;
657 int valid_frames = 0;
659 int frame_index = frame->getFrameNb();
661 if (isFrameValid(source, frame_index)) {
663 auto stamp_rect = getFittingRect(source, frame_index);
664 auto frame_model = createFrameModel(source,
pixel_scale, manager, frame, stamp_rect);
665 auto final_stamp = frame_model.getImage();
667 auto image = createImageCopy(source, frame_index);
669 for (
int y = 0; y < image->getHeight(); ++y) {
670 for (
int x = 0; x < image->getWidth(); ++x) {
671 image->at(x, y) -= deblend_image->at(x, y);
675 auto weight = createWeightImage(source, frame_index);
680 total_data_points += data_points;
681 total_chi_squared += chi_squared;
685 return total_chi_squared;
static Logging getLogger(const std::string &name="")
Data vs model comparator which computes a modified residual, using asinh.
Class responsible for managing the parameters the least square engine minimizes.
static std::shared_ptr< LeastSquareEngine > create(const std::string &name, unsigned max_iterations=1000)
Provides to the LeastSquareEngine the residual values.
void registerBlockProvider(std::unique_ptr< ResidualBlockProvider > provider)
Registers a ResidualBlockProvider to the ResidualEstimator.
static Elements::Logging logger
std::unique_ptr< DataVsModelResiduals< typename std::remove_reference< DataType >::type, typename std::remove_reference< ModelType >::type, typename std::remove_reference< WeightType >::type, typename std::remove_reference< Comparator >::type > > createDataVsModelResiduals(DataType &&data, ModelType &&model, WeightType &&weight, Comparator &&comparator)
T dynamic_pointer_cast(T... args)
Class containing the summary information of solving a least square minimization problem.
std::vector< double > parameter_sigmas
1-sigma margin of error for all the parameters