TransformationModelLinear::TransformationModelLinear( const TransformationModel::DataPoints & data, const Param & params) { params_ = params; data_given_ = !data.empty(); if (!data_given_ && params.exists("slope") && (params.exists("intercept"))) { // don't estimate parameters, use given values slope_ = params.getValue("slope"); intercept_ = params.getValue("intercept"); } else // estimate parameters from data { Param defaults; getDefaultParameters(defaults); params_.setDefaults(defaults); symmetric_ = params_.getValue("symmetric_regression") == "true"; size_t size = data.size(); if (size == 0) // no data { throw Exception::IllegalArgument(__FILE__, __LINE__, __PRETTY_FUNCTION__, "no data points for 'linear' model"); } else if (size == 1) // degenerate case, but we can still do something { slope_ = 1.0; intercept_ = data[0].second - data[0].first; } else // compute least-squares fit { vector<double> x(size), y(size); for (size_t i = 0; i < size; ++i) { if (symmetric_) { x[i] = data[i].second + data[i].first; y[i] = data[i].second - data[i].first; } else { x[i] = data[i].first; y[i] = data[i].second; } } double cov00, cov01, cov11, sumsq; // covariance values, sum of squares double * x_start = &(x[0]), * y_start = &(y[0]); gsl_fit_linear(x_start, 1, y_start, 1, size, &intercept_, &slope_, &cov00, &cov01, &cov11, &sumsq); if (symmetric_) // undo coordinate transformation: { slope_ = (1.0 + slope_) / (1.0 - slope_); intercept_ = intercept_ * 1.41421356237309504880; // 1.41... = sqrt(2) } } } }
TransformationModelLinear::TransformationModelLinear(const TransformationModel::DataPoints& data, const Param& params) : TransformationModel(data, params) // initializes model { data_given_ = !data.empty(); if (!data_given_ && params.exists("slope") && params.exists("intercept")) { // don't estimate parameters, use given values slope_ = params.getValue("slope"); intercept_ = params.getValue("intercept"); } else // estimate parameters from data { Param defaults; getDefaultParameters(defaults); params_.setDefaults(defaults); symmetric_ = params_.getValue("symmetric_regression") == "true"; // weight the data (if weighting is specified) TransformationModel::DataPoints data_weighted = data; if ((params.exists("x_weight") && params.getValue("x_weight") != "") || (params.exists("y_weight") && params.getValue("y_weight") != "")) { weightData(data_weighted); } size_t size = data_weighted.size(); std::vector<Wm5::Vector2d> points; if (size == 0) // no data { throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "no data points for 'linear' model"); } else if (size == 1) // degenerate case, but we can still do something { slope_ = 1.0; intercept_ = data_weighted[0].second - data_weighted[0].first; } else // compute least-squares fit { for (size_t i = 0; i < size; ++i) { points.push_back(Wm5::Vector2d(data_weighted[i].first, data_weighted[i].second)); } if (!Wm5::HeightLineFit2<double>(static_cast<int>(size), &points.front(), slope_, intercept_)) { throw Exception::UnableToFit(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "TransformationModelLinear", "Unable to fit linear transformation to data points."); } } // update params params_.setValue("slope", slope_); params_.setValue("intercept", intercept_); } }