4 #ifndef DP3_COMMON_PHASE_LINE_FITTER_H_
5 #define DP3_COMMON_PHASE_LINE_FITTER_H_
11 #include <aocommon/optionalnumber.h>
33 inline double SlopeModelCost(
const std::vector<FitSample>& data,
double slope) {
35 double weight_sum = 0.0;
37 const double y_model = slope * sample.x;
38 double sample_cost = std::fmod(std::abs(y_model - sample.y), 2.0 * M_PI);
39 if (sample_cost > M_PI) sample_cost = 2.0 * M_PI - sample_cost;
40 sample_cost *= sample.weight;
42 weight_sum += sample.weight;
44 if (weight_sum == 0.0)
47 return cost / weight_sum;
51 double unwrapping_slope) {
56 double numerator = 0.0;
57 double denominator = 0.0;
59 const double y_model = unwrapping_slope * sample.x;
60 double difference = std::fmod(sample.y - y_model, 2.0 * M_PI);
61 if (difference >= M_PI)
62 difference -= 2.0 * M_PI;
63 else if (difference < -M_PI)
64 difference += 2.0 * M_PI;
65 const double unwrapped_y = y_model + difference;
66 const double w_times_x = sample.x * sample.weight;
67 numerator += w_times_x * unwrapped_y;
68 denominator += w_times_x * sample.x;
70 if (denominator != 0.0)
71 return numerator / denominator;
91 const std::vector<FitSample>& data,
92 aocommon::OptionalNumber<int> wrap_count_limit = {}) {
93 if (data.empty())
return SlopeFitRange{0, 0.0};
95 double min_delta = std::numeric_limits<double>::max();
96 for (
size_t i = 0; i != data.size() - 1; ++i) {
97 const double delta = data[i + 1].x - data[i].x;
99 if (delta > 0.0 && delta < min_delta) min_delta = delta;
101 const double min_x = data.front().x;
102 const double max_x = data.back().x;
103 const double max_abs_x = max_x < 0.0 ? -min_x : max_x;
112 int max_wraps = std::ceil(max_abs_x / min_delta);
119 if (data.size() < 20) {
120 constexpr
int extra_space = 10;
121 max_wraps = std::min(max_wraps, extra_space * (2 << data.size()));
124 if (wrap_count_limit) {
125 max_wraps = std::min(max_wraps, *wrap_count_limit);
133 const double wrap_step = M_PI / max_abs_x;
135 return SlopeFitRange{max_wraps, wrap_step};
143 inline double FitSlope(
const std::vector<FitSample>& data,
145 double best_cost = std::numeric_limits<double>::max();
146 double best_estimate = 0.0;
151 if (cost < best_cost) {
185 inline double FitSlope(
const std::vector<FitSample>& data) {
bool estimate(size_t nDirection, size_t nStation, size_t nBaseline, size_t nChannel, const_cursor< Baseline > baselines, std::vector< const_cursor< std::complex< float >>> data, std::vector< const_cursor< std::complex< double >>> model, const_cursor< bool > flag, const_cursor< float > weight, const_cursor< std::complex< double >> mix, double *unknowns, size_t maxiter=50)
Definition: PhaseLineFitter.h:13
SlopeFitRange GetRange(const std::vector< FitSample > &data, aocommon::OptionalNumber< int > wrap_count_limit={})
Definition: PhaseLineFitter.h:90
double UnwrapAndFit(const std::vector< FitSample > &data, double unwrapping_slope)
Definition: PhaseLineFitter.h:50
double FitSlope(const std::vector< FitSample > &data, const SlopeFitRange &range)
Definition: PhaseLineFitter.h:143
double SlopeModelCost(const std::vector< FitSample > &data, double slope)
Definition: PhaseLineFitter.h:33
Definition: PhaseLineFitter.h:15
double y
Definition: PhaseLineFitter.h:24
double x
Definition: PhaseLineFitter.h:20
double weight
Definition: PhaseLineFitter.h:25
Definition: PhaseLineFitter.h:28
double wrap_step
Definition: PhaseLineFitter.h:30
int max_wraps
Definition: PhaseLineFitter.h:29