mirror of
https://github.com/pim-n/pg-rad
synced 2026-03-11 19:58:11 +01:00
Improve PEP8 adherance using flake8 linter
This commit is contained in:
@ -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
|
||||
|
||||
Reference in New Issue
Block a user