Improve PEP8 adherance using flake8 linter

This commit is contained in:
Pim Nelissen
2026-02-05 14:19:49 +01:00
parent dcc3be1c22
commit c23ea40ec6
8 changed files with 117 additions and 81 deletions

View File

@ -11,6 +11,7 @@ from pg_rad.exceptions import ConvergenceError
logger = logging.getLogger(__name__)
class PathSegment:
def __init__(self, a: tuple[float, float], b: tuple[float, float]):
"""A straight Segment of a Path, from (x_a, y_a) to (x_b, y_b).
@ -18,18 +19,18 @@ class PathSegment:
Args:
a (tuple[float, float]): The starting point (x_a, y_a).
b (tuple[float, float]): The final point (x_b, y_b).
"""
"""
self.a = a
self.b = b
def get_length(self) -> float:
return math.dist(self.a, self.b)
length = property(get_length)
def __str__(self) -> str:
return str(f"({self.a}, {self.b})")
def __getitem__(self, index) -> float:
if index == 0:
return self.a
@ -38,26 +39,30 @@ class PathSegment:
else:
raise IndexError
class Path:
def __init__(
self,
coord_list: Sequence[tuple[float, float]],
z: float = 0,
path_simplify = False
path_simplify: bool = False
):
"""Construct a path of sequences based on a list of coordinates.
Args:
coord_list (Sequence[tuple[float, float]]): List of x,y coordinates.
coord_list (Sequence[tuple[float, float]]): List of x,y
coordinates.
z (float, optional): Height of the path. Defaults to 0.
path_simplify (bool, optional): Whether to pg_rad.path.simplify_path(). Defaults to False.
"""
path_simplify (bool, optional): Whether to
pg_rad.path.simplify_path(). Defaults to False.
"""
if len(coord_list) < 2:
raise ValueError("Must provide at least two coordinates as a list of tuples, e.g. [(x1, y1), (x2, y2)]")
raise ValueError("Must provide at least two coordinates as a \
of tuples, e.g. [(x1, y1), (x2, y2)]")
x, y = tuple(zip(*coord_list))
if path_simplify:
try:
x, y = simplify_path(list(x), list(y))
@ -69,7 +74,11 @@ class Path:
coord_list = list(zip(x, y))
self.segments = [PathSegment(i, ip1) for i, ip1 in zip(coord_list, coord_list[1:])]
self.segments = [
PathSegment(i, ip1)
for i, ip1 in
zip(coord_list, coord_list[1:])
]
self.z = z
@ -77,7 +86,7 @@ class Path:
def get_length(self) -> float:
return sum([s.length for s in self.segments])
length = property(get_length)
def __getitem__(self, index) -> PathSegment:
@ -85,40 +94,43 @@ class Path:
def __str__(self) -> str:
return str([str(s) for s in self.segments])
def plot(self, **kwargs):
"""
Plot the path using matplotlib.
"""
"""
plt.plot(self.x_list, self.y_list, **kwargs)
def simplify_path(
x: Sequence[float],
y: Sequence[float],
keep_endpoints_equal: bool = False,
n_breakpoints: int = 3
):
"""From full resolution x and y arrays, return a piecewise linearly approximated/simplified pair of x and y arrays.
"""From full resolution x and y arrays, return a piecewise linearly
approximated/simplified pair of x and y arrays.
This function uses the `piecewise_regression` package. From a full set of
coordinate pairs, the function fits linear sections, automatically finding
the number of breakpoints and their positions.
On why the default value of n_breakpoints is 3, from the `piecewise_regression`
docs:
On why the default value of n_breakpoints is 3, from the
`piecewise_regression` docs:
"If you do not have (or do not want to use) initial guesses for the number
of breakpoints, you can set it to n_breakpoints=3, and the algorithm will
randomly generate start_values. With a 50% chance, the bootstrap restarting
algorithm will either use the best currently converged breakpoints or
randomly generate new start_values, escaping the local optima in two ways in
order to find better global optima."
randomly generate new start_values, escaping the local optima in two ways
in order to find better global optima."
Args:
x (Sequence[float]): Full list of x coordinates.
y (Sequence[float]): Full list of y coordinates.
keep_endpoints_equal (bool, optional): Whether or not to force start
and end to be exactly equal to the original. This will worsen the linear
approximation at the beginning and end of path. Defaults to False.
and end to be exactly equal to the original. This will worsen the
linear approximation at the beginning and end of path. Defaults to
False.
n_breakpoints (int, optional): Number of breakpoints. Defaults to 3.
Returns:
@ -129,25 +141,27 @@ def simplify_path(
ConvergenceError: If the fitting algorithm failed to simplify the path.
Reference:
Pilgrim, C., (2021). piecewise-regression (aka segmented regression) in Python. Journal of Open Source Software, 6(68), 3859, https://doi.org/10.21105/joss.03859.
Pilgrim, C., (2021). piecewise-regression (aka segmented regression)
in Python. Journal of Open Source Software,
6(68), 3859, https://doi.org/10.21105/joss.03859.
"""
logger.debug(f"Attempting piecewise regression on path.")
logger.debug("Attempting piecewise regression on path.")
pw_fit = piecewise_regression.Fit(x, y, n_breakpoints=n_breakpoints)
pw_res = pw_fit.get_results()
if pw_res == None:
if pw_res is None:
logger.warning("Piecewise regression failed to converge.")
raise ConvergenceError("Piecewise regression failed to converge.")
raise ConvergenceError("Piecewise regression failed to converge.")
est = pw_res['estimates']
# extract and sort breakpoints
breakpoints_x = sorted(
v['estimate'] for k, v in est.items() if k.startswith('breakpoint')
)
x_points = [x[0]] + breakpoints_x + [x[-1]]
y_points = pw_fit.predict(x_points)
@ -158,28 +172,33 @@ def simplify_path(
y_points[-1] = y[-1]
logger.info(
f"Piecewise regression reduced path from {len(x)-1} to {len(x_points)-1} segments."
f"Piecewise regression reduced path from \
{len(x)-1} to {len(x_points)-1} segments."
)
return x_points, y_points
def path_from_RT90(
df: pd.DataFrame,
east_col: str = "East",
north_col: str = "North",
**kwargs
) -> Path:
"""Construct a path from East and North formatted coordinates (RT90) in a Pandas DataFrame.
"""Construct a path from East and North formatted coordinates (RT90)
in a Pandas DataFrame.
Args:
df (pandas.DataFrame): DataFrame containing at least the two columns noted in the cols argument.
df (pandas.DataFrame): DataFrame containing at least the two columns
noted in the cols argument.
east_col (str): The column name for the East coordinates.
north_col (str): The column name for the North coordinates.
Returns:
Path: A Path object built from the aquisition coordinates in the DataFrame.
"""
Path: A Path object built from the aquisition coordinates in the
DataFrame.
"""
east_arr = np.array(df[east_col]) - min(df[east_col])
north_arr = np.array(df[north_col]) - min(df[north_col])
@ -187,4 +206,4 @@ def path_from_RT90(
path = Path(coord_pairs, **kwargs)
logger.debug("Loaded path from provided RT90 coordinates.")
return path
return path