Least squares circle — SciPy Cookbook documentation (2024)

  • Contents »
  • Optimization and fitting »
  • Least squares circle
  • GithubDownload
Date:2011-03-22 (last modified), 2011-03-19 (created)

Introduction

This page gathers different methods used to find the least squarescircle fitting a set of 2D points (x,y).

The full code of this analysis is available here:least_squares_circle_v1d.py.

Finding the least squares circle corresponds to finding the center ofthe circle (xc, yc) and its radius Rc which minimize the residu functiondefined below:

In[]:

#! pythonRi = sqrt( (x - xc)**2 + (y - yc)**2)residu = sum( (Ri - Rc)**2)

This is a nonlinear problem. We well see three approaches to theproblem, and compare there results, as well as their speeds.

Using an algebraic approximation

As detailed in thisdocumentthis problem can be approximated by a linear one if we define thefunction to minimize as follow:

This leads to the following method, using linalg.solve :

In[]:

#! python# == METHOD 1 ==method_1 = 'algebraic'# coordinates of the barycenterx_m = mean(x)y_m = mean(y)# calculation of the reduced coordinatesu = x - x_mv = y - y_m# linear system defining the center (uc, vc) in reduced coordinates:# Suu * uc + Suv * vc = (Suuu + Suvv)/2# Suv * uc + Svv * vc = (Suuv + Svvv)/2Suv = sum(u*v)Suu = sum(u**2)Svv = sum(v**2)Suuv = sum(u**2 * v)Suvv = sum(u * v**2)Suuu = sum(u**3)Svvv = sum(v**3)# Solving the linear systemA = array([ [ Suu, Suv ], [Suv, Svv]])B = array([ Suuu + Suvv, Svvv + Suuv ])/2.0uc, vc = linalg.solve(A, B)xc_1 = x_m + ucyc_1 = y_m + vc# Calcul des distances au centre (xc_1, yc_1)Ri_1 = sqrt((x-xc_1)**2 + (y-yc_1)**2)R_1 = mean(Ri_1)residu_1 = sum((Ri_1-R_1)**2)

Using scipy.optimize.leastsq

Scipy comes will several tools to solve the nonlinear problem above.Among them,scipy.optimize.leastsqis very simple to use in this case.

Indeed, once the center of the circle is defined, the radius can becalculated directly and is equal to mean(Ri). So there is only twoparameters left: xc and yc.

Basic usage

In[]:

#! python# == METHOD 2 ==from scipy import optimizemethod_2 = "leastsq"def calc_R(xc, yc): """ calculate the distance of each 2D points from the center (xc, yc) """ return sqrt((x-xc)**2 + (y-yc)**2)def f_2(c): """ calculate the algebraic distance between the data points and the mean circle centered at c=(xc, yc) """ Ri = calc_R(*c) return Ri - Ri.mean()center_estimate = x_m, y_mcenter_2, ier = optimize.leastsq(f_2, center_estimate)xc_2, yc_2 = center_2Ri_2 = calc_R(*center_2)R_2 = Ri_2.mean()residu_2 = sum((Ri_2 - R_2)**2)

Advanced usage, with jacobian function

To gain in speed, it is possible to tell optimize.leastsq how to computethe jacobian of the function by adding a Dfun argument:

In[]:

#! python# == METHOD 2b ==method_2b = "leastsq with jacobian"def calc_R(xc, yc): """ calculate the distance of each data points from the center (xc, yc) """ return sqrt((x-xc)**2 + (y-yc)**2)def f_2b(c): """ calculate the algebraic distance between the 2D points and the mean circle centered at c=(xc, yc) """ Ri = calc_R(*c) return Ri - Ri.mean()def Df_2b(c): """ Jacobian of f_2b The axis corresponding to derivatives must be coherent with the col_deriv option of leastsq""" xc, yc = c df2b_dc = empty((len(c), x.size)) Ri = calc_R(xc, yc) df2b_dc[0] = (xc - x)/Ri # dR/dxc df2b_dc[1] = (yc - y)/Ri # dR/dyc df2b_dc = df2b_dc - df2b_dc.mean(axis=1)[:, newaxis] return df2b_dccenter_estimate = x_m, y_mcenter_2b, ier = optimize.leastsq(f_2b, center_estimate, Dfun=Df_2b, col_deriv=True)xc_2b, yc_2b = center_2bRi_2b = calc_R(*center_2b)R_2b = Ri_2b.mean()residu_2b = sum((Ri_2b - R_2b)**2)

Using scipy.odr

Scipy has a dedicated package to deal with orthogonal distanceregression, namelyscipy.odr. Thispackage can handle both explict and implicit function definition, and wewill used the second form in this case.

Here is the implicit definition of the circle:

In[]:

#! python(x - xc)**2 + (y-yc)**2 - Rc**2 = 0

Basic usage

This leads to the following code:

In[]:

#! python# == METHOD 3 ==from scipy import odrmethod_3 = "odr"def f_3(beta, x): """ implicit definition of the circle """ return (x[0]-beta[0])**2 + (x[1]-beta[1])**2 -beta[2]**2# initial guess for parametersR_m = calc_R(x_m, y_m).mean()beta0 = [ x_m, y_m, R_m]# for implicit function :# data.x contains both coordinates of the points (data.x = [x, y])# data.y is the dimensionality of the responselsc_data = odr.Data(row_stack([x, y]), y=1)lsc_model = odr.Model(f_3, implicit=True)lsc_odr = odr.ODR(lsc_data, lsc_model, beta0)lsc_out = lsc_odr.run()xc_3, yc_3, R_3 = lsc_out.betaRi_3 = calc_R([xc_3, yc_3])residu_3 = sum((Ri_3 - R_3)**2)

Advanced usage, with jacobian functions

One of the advantages of the implicit function definition is that itsderivatives are very easily calculated.

This can be used to complete the model:

In[]:

#! python# == METHOD 3b ==method_3b = "odr with jacobian"def f_3b(beta, x): """ implicit definition of the circle """ return (x[0]-beta[0])**2 + (x[1]-beta[1])**2 -beta[2]**2def jacb(beta, x): """ Jacobian function with respect to the parameters beta. return df_3b/dbeta """ xc, yc, r = beta xi, yi = x df_db = empty((beta.size, x.shape[1])) df_db[0] = 2*(xc-xi) # d_f/dxc df_db[1] = 2*(yc-yi) # d_f/dyc df_db[2] = -2*r # d_f/dr return df_dbdef jacd(beta, x): """ Jacobian function with respect to the input x. return df_3b/dx """ xc, yc, r = beta xi, yi = x df_dx = empty_like(x) df_dx[0] = 2*(xi-xc) # d_f/dxi df_dx[1] = 2*(yi-yc) # d_f/dyi return df_dxdef calc_estimate(data): """ Return a first estimation on the parameter from the data """ xc0, yc0 = data.x.mean(axis=1) r0 = sqrt((data.x[0]-xc0)**2 +(data.x[1] -yc0)**2).mean() return xc0, yc0, r0# for implicit function :# data.x contains both coordinates of the points# data.y is the dimensionality of the responselsc_data = odr.Data(row_stack([x, y]), y=1)lsc_model = odr.Model(f_3b, implicit=True, estimate=calc_estimate, fjacd=jacd, fjacb=jacb)lsc_odr = odr.ODR(lsc_data, lsc_model) # beta0 has been replaced by an estimate functionlsc_odr.set_job(deriv=3) # use user derivatives function without checkinglsc_odr.set_iprint(iter=1, iter_step=1) # print details for each iterationlsc_out = lsc_odr.run()xc_3b, yc_3b, R_3b = lsc_out.betaRi_3b = calc_R(xc_3b, yc_3b)residu_3b = sum((Ri_3b - R_3b)**2)

Comparison of the three methods

We will compare the results of these three methods in two cases:

*when2Dpointsareallaroundthecircle

*when2Dpointsareinasmallarc

Data points all around the circle

Here is an example with data points all around the circle:

In[]:

#! python# Coordinates of the 2D pointsx = r_[ 9, 35, -13, 10, 23, 0]y = r_[ 34, 10, 6, -14, 27, -10]

This gives:

||||||||||||||||<tablewidth="100%">SUMMARY|| ||Method|| Xc|| Yc || Rc ||nb_calls || std(Ri)|| residu ||residu2 || ||algebraic || 10.55231 || 9.70590|| 23.33482|| 1||1.135135|| 7.731195|| 16236.34|| ||leastsq || 10.50009 || 9.65995||23.33353|| 15|| 1.133715|| 7.711852|| 16276.89|| ||leastsq with jacobian|| 10.50009 || 9.65995|| 23.33353|| 7|| 1.133715|| 7.711852|| 16276.89||||odr || 10.50009 || 9.65995|| 23.33353|| 82|| 1.133715|| 7.711852||16276.89|| ||odr with jacobian || 10.50009 || 9.65995|| 23.33353|| 16||1.133715|| 7.711852|| 16276.89||

Note:

*`nb_calls`correspondtothenumberoffunctioncallsofthefunctiontobeminimized,anddonottakeintoaccountthenumberofcallstoderivativesfunction.ThisdiffersfromthenumberofiterationasODRcanmakemultiplecallsduringaniteration.

*asshownonthefiguresbelow,thetwofunctions`residu`and`residu_2`arenotequivalent,buttheirminimaarecloseinthiscase.

Least squares circle — SciPy Cookbook documentation (1) Least squares circle — SciPy Cookbook documentation (2)

Data points around an arc

Here is an example where data points form an arc:

In[]:

#! pythonx = r_[36, 36, 19, 18, 33, 26]y = r_[14, 10, 28, 31, 18, 26]
'''Method''' '''Xc''' '''Yc''' '''Rc''' '''nb_calls''' '''std(Ri)''' '''residu''' '''residu2'''
algebraic 15.05503 8.83615 20.82995 1 0.930508 5.195076 9153.40
leastsq 9.88760 3.68753 27.35040 24 0.820825 4.042522 12001.98
leastsq with jacobian 9.88759 3.68752 27.35041 10 0.820825 4.042522 12001.98
odr 9.88757 3.68750 27.35044 472 0.820825 4.042522 12002.01
odr with jacobian 9.88757 3.68750 27.35044 109 0.820825 4.042522 12002.01

arc_v5.pngarc_residu2_v6.png

Conclusion

ODR and leastsq gives the same results.

Optimize.leastsq is the most efficient method, and can be two to ten times faster than ODR, at least as regards the number of function call.

Adding a function to compute the jacobian can lead to decrease the number of function calls by a factor of two to five.

In this case, to use ODR seems a bit overkill but it can be very handy for more complex use cases like ellipses.

The algebraic approximation gives good results when the points are all around the circle but is limited when there is only an arc to fit.

Indeed, the two errors functions to minimize are not equivalent when data points are not all exactly on a circle. The algebraic method leads in most of the case to a smaller radius than that of the least squares circle, as its error function is based on squared distances and not on the distance themselves.

Section author: Elby

Attachments

  • arc_residu2_v1.png
  • arc_residu2_v2.png
  • arc_residu2_v3.png
  • arc_residu2_v4.png
  • arc_residu2_v5.png
  • arc_residu2_v6.png
  • arc_v1.png
  • arc_v2.png
  • arc_v3.png
  • arc_v4.png
  • arc_v5.png
  • full_cercle_residu2_v1.png
  • full_cercle_residu2_v2.png
  • full_cercle_residu2_v3.png
  • full_cercle_residu2_v4.png
  • full_cercle_residu2_v5.png
  • full_cercle_v1.png
  • full_cercle_v2.png
  • full_cercle_v3.png
  • full_cercle_v4.png
  • full_cercle_v5.png
  • least_squares_circle.py
  • least_squares_circle_v1.py
  • least_squares_circle_v1b.py
  • least_squares_circle_v1c.py
  • least_squares_circle_v1d.py
  • least_squares_circle_v2.py
  • least_squares_circle_v3.py
Least squares circle — SciPy Cookbook  documentation (2024)

FAQs

What is the least squares circle? ›

The least squares circle (LSC) is fitted inside the profile such that the sum of the squares of radial ordinates between the circle and profile is minimized as illustrated in Figure 2.

What is the least squares method in Python? ›

In Python, the least squares method is used internally by the model to calculate the slope (coefficient) and intercept of the best-fitting line. The line itself is the result of this method.

What is least squares for dummies? ›

The least squares principle states that the SRF should be constructed (with the constant and slope values) so that the sum of the squared distance between the observed values of your dependent variable and the values estimated from your SRF is minimized (the smallest possible value).

What does least squares tell you? ›

The least squares method is a statistical procedure to find the best fit for a set of data points. The method works by minimizing the sum of the offsets or residuals of points from the plotted curve. Least squares regression is used to predict the behavior of dependent variables.

What is the least squares reference circle? ›

Least Square Reference Circle (LSC)

The Least Squares reference circle is a circle where the sum of areas inside this circle are equal to the sum of the areas outside the circle and kept to a minimum separation.

How do you find the least squares? ›

The least-squares regression line equation is y = mx + b, where m is the slope, which is equal to (Nsum(xy) - sum(x)sum(y))/(Nsum(x^2) - (sum x)^2), and b is the y-intercept, which is equals to (sum(y) - msum(x))/N. N is the number of data points, and x and y are the coordinates of the data points.

What is the least square curve? ›

The least-square method states that the curve that best fits a given set of observations, is said to be a curve having a minimum sum of the squared residuals (or deviations or errors) from the given data points.

What is the little circle in math called? ›

The open circle symbol ∘ is called the composition operator. We use this operator mainly when we wish to emphasize the relationship between the functions themselves without referring to any particular input value.

Top Articles
Best Phone Plans w/ Military & Veteran Family Discounts | T-Mobile
Vue Dublin Cinema | Dublin Cinema Film Listings & Times | Vue
2016 Hyundai Sonata Refrigerant Capacity
Rentals for rent in Maastricht
Old Bahama Bay Quad Folding Wagon
What Is The Value Of 53I 9
Craigslist Pets Longview Tx
Rick Harrison Daughter Ciana
Mets Game Highlights
The Land Book 9 Release Date 2023
Which Statement About These Two Restaurant Meals Is Correct
The Goddess Collection
Mobile Maher Terminal
Inside the Rise and Fall of Toys ‘R’ Us | HISTORY
Jennette Mccurdy Tmz Hawaii
Th 8 Best Army
Leaf Blower and Vacuum Vacuum Hoses
Model Center Jasmin
American Eagle Store Locator
HRConnect Core Applications
2012 Buick Lacrosse Serpentine Belt Diagram
Hartford Healthcare Employee Tools
Beetrose 'Planten un Blomen' - Rosa 'Planten un Blomen' ADR-Rose
Antonios Worcester Menu
Baddiehub Cover
Fedex Express Ship Center
Dramacool Love In Contract
Does Iherb Accept Ebt
Boggle Brainbusters Bonus
Roe V. Wade: The Abortion Rights Controversy in American History?second Edition, Revised and Expanded (Landmark Law Cases and American Society) - Taylor, Bob: 9780700617548
Brgeneral Patient Portal
Inland Empire Heavy Equipment For Sale By Owner
Craigslist Tools Las Cruces Nm
10 Teacher Tips to Encourage Self-Awareness in Teens | EVERFI
Dc Networks Claimant Services
Skip The Games Albany
Green Press Gazette Obits
Rockin That Orange Jumpsuit Columbia County
Depths Charm Calamity
Part Of The Body With The Humerus And Radius Nyt
Directions To Pnc Near Me
M&T Bank Branch Locations
Mybrownhanky Com
50 Shades Of Grey Movie 123Movies
Portmanteau Structure Built With Cans
Epaper Dunya
Uncc Class Schedule
Watermelon Cucumber Basil Lemonade - Wine a Little, Cook a Lot
Bass Tracker Boats For Sale On Craigslist
Jaggers Nutrition Menu
Latest Posts
Article information

Author: Kareem Mueller DO

Last Updated:

Views: 6327

Rating: 4.6 / 5 (46 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Kareem Mueller DO

Birthday: 1997-01-04

Address: Apt. 156 12935 Runolfsdottir Mission, Greenfort, MN 74384-6749

Phone: +16704982844747

Job: Corporate Administration Planner

Hobby: Mountain biking, Jewelry making, Stone skipping, Lacemaking, Knife making, Scrapbooking, Letterboxing

Introduction: My name is Kareem Mueller DO, I am a vivacious, super, thoughtful, excited, handsome, beautiful, combative person who loves writing and wants to share my knowledge and understanding with you.