CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-circle-fit

A comprehensive collection of circle fitting algorithms for Python that enable finding optimal circle parameters from 2D point data.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

index.mddocs/

Circle-Fit

A comprehensive collection of circle fitting algorithms for Python that enable finding optimal circle parameters from 2D point data. Circle-fit implements multiple sophisticated algorithms including hyperLSQ for high-accuracy least squares fitting, standardLSQ for basic least squares, various SVD-based algebraic approaches (Pratt, Taubin, hyperSVD), geometric methods (Riemann SWFL), iterative optimization (Levenberg-Marquardt), and consistent fitting (KMH method). All algorithms provide a uniform API and support both Python lists and NumPy arrays as input.

Package Information

  • Package Name: circle-fit
  • Language: Python
  • Installation: pip install circle-fit

Core Imports

from circle_fit import taubinSVD, hyperLSQ, standardLSQ, plot_data_circle
from typing import Union, List, Tuple
import numpy as np
import numpy.typing as npt

Import all available algorithms:

from circle_fit import (
    riemannSWFLa, lm, prattSVD, taubinSVD, hyperSVD, 
    kmh, hyperLSQ, standardLSQ, plot_data_circle
)
from typing import Union, List, Tuple
import numpy as np
import numpy.typing as npt

Legacy aliases:

from circle_fit import hyper_fit, least_squares_circle

Basic Usage

from circle_fit import taubinSVD, plot_data_circle
import numpy as np

# Create sample 2D points (as Python list)
point_coordinates = [[1, 0], [-1, 0], [0, 1], [0, -1]]

# Fit a circle using Taubin SVD algorithm (recommended default)
xc, yc, r, sigma = taubinSVD(point_coordinates)
print(f"Center: ({xc:.3f}, {yc:.3f}), Radius: {r:.3f}, Error: {sigma:.6f}")

# Also works with NumPy arrays
points_array = np.array([[1, 0], [-1, 0], [0, 1], [0, -1]])
xc, yc, r, sigma = taubinSVD(points_array)

# Visualize the fit (requires matplotlib)
plot_data_circle(point_coordinates, xc, yc, r)

Capabilities

Recommended Algorithm

For most use cases, taubinSVD() provides a good balance of accuracy and robustness.

def taubinSVD(coords: Union[npt.NDArray, List]) -> Tuple[float, ...]:
    """
    Algebraic circle fit by G. Taubin using SVD.
    
    Parameters:
    - coords: 2D List or 2D np.ndarray of shape (n,2). X,Y point coordinates.
    
    Returns:
    tuple: (xc, yc, r, sigma) where:
        - xc (float): x coordinate of circle center
        - yc (float): y coordinate of circle center  
        - r (float): radius of fitted circle
        - sigma (float): RMS error of the fit
    """

High-Accuracy Least Squares

For maximum accuracy when precision is critical.

def hyperLSQ(coords: Union[npt.NDArray, List], iter_max: int = 99) -> Tuple[float, ...]:
    """
    Hyper least squares fitting with "hyperaccuracy" by Kenichi Kanatani, Prasanna Rangarajan.
    
    Parameters:
    - coords: 2D List or 2D np.ndarray of shape (n,2). X,Y point coordinates.
    - iter_max (int, optional): Maximum number of iterations. Defaults to 99.
    
    Returns:
    tuple: (xc, yc, r, sigma) where:
        - xc (float): x coordinate of circle center
        - yc (float): y coordinate of circle center  
        - r (float): radius of fitted circle
        - sigma (float): RMS error of the fit
    """

Standard Least Squares

Basic least squares circle fitting for simple cases.

def standardLSQ(coords: Union[np.ndarray, List]) -> Tuple[float, ...]:
    """
    Standard least squares circle fitting.
    
    Parameters:
    - coords: 2D List or 2D np.ndarray of shape (n,2). X,Y point coordinates.
    
    Returns:
    tuple: (xc, yc, r, sigma) where:
        - xc (float): x coordinate of circle center
        - yc (float): y coordinate of circle center  
        - r (float): radius of fitted circle
        - sigma (float): RMS error of the fit
    """

Geometric Optimization

Levenberg-Marquardt algorithm minimizing orthogonal distances in full parameter space.

def lm(coords: Union[npt.NDArray, List], par_ini: npt.NDArray, iter_max: int = 50, lambda_ini: float = 1, epsilon: float = 0.00001) -> Tuple[float, ...]:
    """
    Geometric circle fit using Levenberg-Marquardt scheme.
    
    Parameters:
    - coords: 2D List or 2D np.ndarray of shape (n,2). X,Y point coordinates.
    - par_ini: 1D np.ndarray. Array of [xc, yc, r] initial guess.
    - iter_max (int, optional): Maximum iterations. Defaults to 50.
    - lambda_ini (float, optional): Initial correction factor. Defaults to 1.
    - epsilon (float, optional): Convergence threshold. Defaults to 0.00001.
    
    Returns:
    tuple: (xc, yc, r, sigma) where:
        - xc (float): x coordinate of circle center
        - yc (float): y coordinate of circle center  
        - r (float): radius of fitted circle
        - sigma (float): RMS error of the fit
    """

SVD-Based Algebraic Methods

Fast algebraic approaches using Singular Value Decomposition.

def prattSVD(coords: Union[npt.NDArray, List]) -> Tuple[float, ...]:
    """
    Algebraic circle fit by V. Pratt using SVD.
    
    Parameters:
    - coords: 2D List or 2D np.ndarray of shape (n,2). X,Y point coordinates.
    
    Returns:
    tuple: (xc, yc, r, sigma) where:
        - xc (float): x coordinate of circle center
        - yc (float): y coordinate of circle center  
        - r (float): radius of fitted circle
        - sigma (float): RMS error of the fit
    """

def hyperSVD(coords: Union[npt.NDArray, List]) -> Tuple[float, ...]:
    """
    Algebraic circle fit with "hyperaccuracy" using SVD.
    
    Parameters:
    - coords: 2D List or 2D np.ndarray of shape (n,2). X,Y point coordinates.
    
    Returns:
    tuple: (xc, yc, r, sigma) where:
        - xc (float): x coordinate of circle center
        - yc (float): y coordinate of circle center  
        - r (float): radius of fitted circle
        - sigma (float): RMS error of the fit
    """

Specialized Algorithms

Advanced algorithms for specific use cases.

def riemannSWFLa(coords: Union[npt.NDArray, List]) -> Tuple[float, ...]:
    """
    Riemann circle fit, SWFL version A by Strandlie, Wroldsen, Fruhwirth, and Lillekjendlie.
    
    Parameters:
    - coords: 2D List or 2D np.ndarray of shape (n,2). X,Y point coordinates.
    
    Returns:
    tuple: (xc, yc, r, sigma) where:
        - xc (float): x coordinate of circle center
        - yc (float): y coordinate of circle center  
        - r (float): radius of fitted circle
        - sigma (float): RMS error of the fit
    """

def kmh(coords: Union[npt.NDArray, List], iter_max: int = 99, epsilon: float = 1E-9) -> Tuple[float, ...]:
    """
    Consistent circle fit by A. Kukush, I. Markovsky, S. Van Huffel.
    
    Parameters:
    - coords: 2D List or 2D np.ndarray of shape (n,2). X,Y point coordinates.
    - iter_max (int, optional): Maximum iterations. Defaults to 99.
    - epsilon (float, optional): Convergence threshold. Defaults to 1E-9.
    
    Returns:
    tuple: (xc, yc, r, sigma) where:
        - xc (float): x coordinate of circle center
        - yc (float): y coordinate of circle center  
        - r (float): radius of fitted circle
        - sigma (float): RMS error of the fit
    """

Visualization

Plot data points with fitted circle overlay.

def plot_data_circle(coords: Union[npt.NDArray, List], xc: float, yc: float, r: float) -> None:
    """
    Plot data points with fitted circle overlay using matplotlib.
    
    Parameters:
    - coords: 2D List or 2D np.ndarray of shape (n,2). X,Y point coordinates.
    - xc (float): x coordinate of circle center
    - yc (float): y coordinate of circle center  
    - r (float): radius of fitted circle
    
    Returns:
    None
    
    Raises:
    ModuleNotFoundError: If matplotlib is not installed.
    """

Legacy Aliases

Deprecated functions provided for backwards compatibility.

def hyper_fit(coords: Union[npt.NDArray, List], IterMax: int = 99) -> Tuple[float, ...]:
    """
    Deprecated alias for hyperLSQ().
    
    Parameters:
    - coords: 2D List or 2D np.ndarray of shape (n,2). X,Y point coordinates.
    - IterMax (int, optional): Maximum iterations. Defaults to 99.
    
    Returns:
    tuple: (xc, yc, r, sigma)
    
    Note:
    This function is deprecated. Use hyperLSQ() instead.
    """

def least_squares_circle(coords: Union[npt.NDArray, List]) -> Tuple[float, ...]:
    """
    Deprecated alias for standardLSQ().
    
    Parameters:
    - coords: 2D List or 2D np.ndarray of shape (n,2). X,Y point coordinates.
    
    Returns:
    tuple: (xc, yc, r, sigma)
    
    Note:
    This function is deprecated. Use standardLSQ() instead.
    """

Types

# Input coordinate formats
CoordinateInput = Union[List[List[float]], npt.NDArray]

# Return type for all fitting functions  
CircleFitResult = Tuple[float, float, float, float]
# (xc: center x, yc: center y, r: radius, sigma: RMS error)

# Initial parameter guess for lm() function
InitialParameters = npt.NDArray  # Shape: (3,) containing [xc, yc, r]

Error Handling

Common exceptions that may be raised:

  • Exception: Raised by convert_input() for unsupported coordinate input types
  • ModuleNotFoundError: Raised by plot_data_circle() when matplotlib is not installed
  • AssertionError: Raised by convert_input() for incorrectly shaped numpy arrays
  • Numerical errors: Various algorithms may encounter numerical instability with degenerate point sets

Usage Examples

Comparing Multiple Algorithms

from circle_fit import taubinSVD, hyperLSQ, standardLSQ
import numpy as np

# Sample noisy circle data
np.random.seed(42)
theta = np.linspace(0, 2*np.pi, 20)
true_center = (5, 3)
true_radius = 10
noise_level = 0.5

x = true_center[0] + true_radius * np.cos(theta) + np.random.normal(0, noise_level, 20)
y = true_center[1] + true_radius * np.sin(theta) + np.random.normal(0, noise_level, 20)
coords = np.column_stack([x, y])

# Compare different algorithms
algorithms = [
    ("Taubin SVD", taubinSVD),
    ("Hyper LSQ", hyperLSQ), 
    ("Standard LSQ", standardLSQ)
]

for name, algorithm in algorithms:
    xc, yc, r, sigma = algorithm(coords)
    print(f"{name}: Center=({xc:.2f}, {yc:.2f}), Radius={r:.2f}, Error={sigma:.4f}")

Using Levenberg-Marquardt with Initial Guess

from circle_fit import lm, taubinSVD
import numpy as np

# First get a rough estimate using Taubin SVD
coords = [[1, 0], [-1, 0], [0, 1], [0, -1], [0.5, 0.8]]
xc_init, yc_init, r_init, _ = taubinSVD(coords)

# Use as initial guess for high-precision LM algorithm
par_ini = np.array([xc_init, yc_init, r_init])
xc, yc, r, sigma = lm(coords, par_ini)
print(f"LM result: Center=({xc:.6f}, {yc:.6f}), Radius={r:.6f}, Error={sigma:.8f}")

Install with Tessl CLI

npx tessl i tessl/pypi-circle-fit

docs

index.md

tile.json