252 lines
8.8 KiB
C++
252 lines
8.8 KiB
C++
// ____ ______ __
|
|
// / __ \ / ____// /
|
|
// / /_/ // / / /
|
|
// / ____// /___ / /___ PixInsight Class Library
|
|
// /_/ \____//_____/ PCL 2.4.23
|
|
// ----------------------------------------------------------------------------
|
|
// pcl/LinearFit.h - Released 2022-03-12T18:59:29Z
|
|
// ----------------------------------------------------------------------------
|
|
// This file is part of the PixInsight Class Library (PCL).
|
|
// PCL is a multiplatform C++ framework for development of PixInsight modules.
|
|
//
|
|
// Copyright (c) 2003-2022 Pleiades Astrophoto S.L. All Rights Reserved.
|
|
//
|
|
// Redistribution and use in both source and binary forms, with or without
|
|
// modification, is permitted provided that the following conditions are met:
|
|
//
|
|
// 1. All redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
//
|
|
// 2. All redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
//
|
|
// 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
|
|
// of their contributors, may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission. For written
|
|
// permission, please contact info@pixinsight.com.
|
|
//
|
|
// 4. All products derived from this software, in any form whatsoever, must
|
|
// reproduce the following acknowledgment in the end-user documentation
|
|
// and/or other materials provided with the product:
|
|
//
|
|
// "This product is based on software from the PixInsight project, developed
|
|
// by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
|
|
//
|
|
// Alternatively, if that is where third-party acknowledgments normally
|
|
// appear, this acknowledgment must be reproduced in the product itself.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
|
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
// EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
|
|
// INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
|
|
// DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#ifndef __PCL_LinearFit_h
|
|
#define __PCL_LinearFit_h
|
|
|
|
/// \file pcl/LinearFit.h
|
|
|
|
#include <pcl/Defs.h>
|
|
|
|
#include <pcl/Exception.h>
|
|
#include <pcl/Math.h>
|
|
|
|
namespace pcl
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class PCL_CLASS StatusMonitor;
|
|
|
|
/*!
|
|
* \class LinearFit
|
|
* \brief Robust straight line fitting by minimization of mean absolute
|
|
* deviation
|
|
*
|
|
* Given a set of N data points {xi,yi} for i = {0,...,N-1}, %LinearFit finds
|
|
* the parameters a,b of the linear function:
|
|
*
|
|
* <pre>y = L(x) := a + b*x</pre>
|
|
*
|
|
* that minimizes mean absolute deviation for all the data points. The \e a
|
|
* parameter of L() is the ordinate of its intersection with the Y axis. The
|
|
* \e b parameter is the slope of the fitted straight line.
|
|
*/
|
|
class PCL_CLASS LinearFit
|
|
{
|
|
public:
|
|
|
|
/*!
|
|
* The \e a parameter of the fitted straight line:
|
|
*
|
|
* <pre>y = a + b*x</pre>
|
|
*
|
|
* is the ordinate of its intersection with the Y axis. It represents a
|
|
* constant additive pedestal present in the whole dataset.
|
|
*/
|
|
double a = 0;
|
|
|
|
/*!
|
|
* The \e b parameter is the slope of the fitted straight line:
|
|
*
|
|
* <pre>y = a + b*x</pre>
|
|
*
|
|
* If the fitted line passes through two points {x1,y1} and {x2,y2}, then
|
|
* its slope is equal to (y2 - y1)/(x2 - x1).
|
|
*/
|
|
double b = 0;
|
|
|
|
/*!
|
|
* Mean absolute deviation of the linear fit. This is the mean absolute
|
|
* deviation computed for all data points with respect to the fitted
|
|
* straight line function.
|
|
*/
|
|
double adev = 0;
|
|
|
|
/*!
|
|
* Returns true iff the fitted straight line model is valid. The model
|
|
* function is valid if the slope parameter is finite, i.e., if the fitted
|
|
* line is not vertical.
|
|
*/
|
|
bool IsValid() const
|
|
{
|
|
return IsFinite( b );
|
|
}
|
|
|
|
/*!
|
|
* Evaluates the fitted line function for the specified abscissa \a x.
|
|
*/
|
|
double operator ()( double x ) const
|
|
{
|
|
return a + b*x;
|
|
}
|
|
|
|
/*!
|
|
* Constructs a default %LinearFit object. The resulting object corresponds
|
|
* to a horizontal line crossing at the origin, i.e. the X axis.
|
|
*/
|
|
LinearFit() = default;
|
|
|
|
/*!
|
|
* Copy constructor.
|
|
*/
|
|
LinearFit( const LinearFit& ) = default;
|
|
|
|
/*!
|
|
* Constructs a %LinearFit object representing the straight line that passes
|
|
* through two points {x1,y1} and {x2,y2}.
|
|
*
|
|
* \warning Do not specify a vertical line, that is, make sure that
|
|
* x1 != x2 w.r.t. the machine epsilon, or this constructor will perform a
|
|
* division by zero.
|
|
*/
|
|
template <typename T>
|
|
LinearFit( T x1, T y1, T x2, T y2 )
|
|
{
|
|
b = double( y2 - y1 )/double( x2 - x1 );
|
|
a = (y2 - b*x2 + y1 - b*x1)/2;
|
|
adev = 0;
|
|
}
|
|
|
|
/*!
|
|
* Constructs a %LinearFit object to fit a straight line for the specified
|
|
* set of data points.
|
|
*
|
|
* \param x %Array of abscissae values.
|
|
*
|
|
* \param y %Array of ordinate values.
|
|
*
|
|
* \param n Number of data points. Must be >= 2.
|
|
*
|
|
* \param status If nonzero, pointer to a StatusMonitor object that will be
|
|
* updated during the fitting process. The linear fit process
|
|
* is \e unbounded, i.e., the total number of monitoring
|
|
* steps cannot be known in advance. The default value is
|
|
* zero (no monitoring).
|
|
*
|
|
* When n >= 3, this constructor fits the straight line that minimizes mean
|
|
* absolute deviation for all the source data points. When n == 2, this
|
|
* function finds the straight line that passes through the two data points.
|
|
* When n < 2, this constructor throws an Error exception.
|
|
*/
|
|
template <typename T>
|
|
LinearFit( const T* x, const T* y, size_type n, StatusMonitor* status = nullptr )
|
|
{
|
|
if ( n < 2 )
|
|
throw Error( "LinearFit::LinearFit(): Less than two data points specified." );
|
|
|
|
if ( n == 2 )
|
|
{
|
|
b = double( y[1] - y[0] )/double( x[1] - x[0] );
|
|
a = (y[1] - b*x[1] + y[0] - b*x[0])/2;
|
|
adev = 0;
|
|
}
|
|
else
|
|
Fit( a, b, adev, x, y, n, status );
|
|
}
|
|
|
|
/*!
|
|
* Constructs a %LinearFit object to fit a straight line for the specified
|
|
* data containers.
|
|
*
|
|
* \param x %Container of abscissae values.
|
|
*
|
|
* \param y %Container of ordinate values.
|
|
*
|
|
* \param status If nonzero, pointer to a StatusMonitor object that will be
|
|
* updated during the fitting process. The linear fit process
|
|
* is \e unbounded, i.e., the total number of monitoring
|
|
* steps cannot be known in advance. The default value is
|
|
* zero (no monitoring).
|
|
*
|
|
* The number \a n of data points is the minimum container length, i.e.:
|
|
*
|
|
* <pre>n = Min( x.Length(), y.Length() )</pre>
|
|
*
|
|
* When n >= 3, this constructor fits the straight line that minimizes mean
|
|
* absolute deviation for all the source data points. When n == 2, this
|
|
* function finds the straight line that passes through the two data points.
|
|
* When n < 2, this constructor throws an Error exception.
|
|
*/
|
|
template <class C>
|
|
LinearFit( const C& x, const C& y, StatusMonitor* status = nullptr )
|
|
{
|
|
size_type n = Min( x.Length(), y.Length() );
|
|
if ( n < 2 )
|
|
throw Error( "LinearFit::LinearFit(): Less than two data points specified." );
|
|
|
|
if ( n == 2 )
|
|
{
|
|
b = double( y[1] - y[0] )/double( x[1] - x[0] );
|
|
a = (y[1] - b*x[1] + y[0] - b*x[0])/2;
|
|
adev = 0;
|
|
}
|
|
else
|
|
Fit( a, b, adev, x.Begin(), y.Begin(), n, status );
|
|
}
|
|
|
|
private:
|
|
|
|
static void Fit( double& a, double& b, double& adev,
|
|
const float* fx, const float* fy, size_type n, StatusMonitor* status );
|
|
static void Fit( double& a, double& b, double& adev,
|
|
const double* fx, const double* fy, size_type n, StatusMonitor* status );
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
} // pcl
|
|
|
|
#endif // __LinearFit_h
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// EOF pcl/LinearFit.h - Released 2022-03-12T18:59:29Z
|