diff --git a/README.md b/README.md index 622c4fa..c9849ad 100644 --- a/README.md +++ b/README.md @@ -386,6 +386,7 @@ Plot the centerline created from a list of right and left banks with Voronoi ver plotCenterline(centerline_type="Voronoi", marker_type="line", centerline_color="black", + dark_mode=False, display_all_possible_paths=False, plot_title=None, save_plot_name=None, @@ -395,6 +396,7 @@ plotCenterline(centerline_type="Voronoi", * [OPTIONAL] centerline_type (string): Centerline type graph within river (not case-sensitive), options: ["Voronoi", "Evenly Spaced", "Smoothed", "Equal Distance"], defaults to "Voronoi" * [OPTIONAL] marker_type (string): Graph type (not case-sensitive), options: ["Line", "Scatter"], defaults to "Line" * [OPTIONAL] centerline_color (string): Color of centerline coordinates on graph (not case-sensitive), options: [matplotlib named colors](https://matplotlib.org/stable/gallery/color/named_colors.html), defaults to "black" +* [OPTIONAL] dark_mode (bool): Change plot to a black ground (and override if `centerline_color="black"` to `centerline_color="white"`), defaults to False * [OPTIONAL] display_all_possible_paths (boolean): Display all possible paths, not just the centerline (useful for debugging), defaults to False * [OPTIONAL] plot_title (string): Change plot title, defaults to "River Coordinates: Valid Centerline = True/False, Valid Polygon = True/False" * [OPTIONAL] save_plot_name (string): Save the plot with a given name and location @@ -421,6 +423,7 @@ plotCenterlineWidth(plot_title=None, apply_smoothing=False, flag_intersections=True, remove_intersections=False, + dark_mode=False, coordinate_unit="Decimal Degrees") ``` * [OPTIONAL] plot_title (string): Change plot title, defaults to "River Coordinates: Valid Centerline = True/False, Valid Polygon = True/False" @@ -430,6 +433,7 @@ plotCenterlineWidth(plot_title=None, * [OPTIONAL] apply_smoothing (boolean): Apply a B-spline smoothing to centerline * [OPTIONAL] flag_intersections (boolean): Display intersecting width lines as red in graph, defaults to True * [OPTIONAL] remove_intersections (boolean): Remove intersecting lines (but maintain the most width lines as possible) and only return non-intersecting width lines, defaults to False +* [OPTIONAL] dark_mode (bool): Change plot to a black ground (and override if `centerline_color="black"` to `centerline_color="white"`), defaults to False * [OPTIONAL] coordinate_unit (string): Coordinates of the river are return as "Decimal Degrees" (latitude/longtidue) or converted to a distance from the first point on the left bank as "Relative Distance", defaults to "Decimal Degrees" **apply_smoothing** @@ -460,6 +464,14 @@ Intersecting lines are flagged in red by default (flag_intersections=True) | ------------- | ------------- | | ![river_keep+png](https://raw.githubusercontent.com/cyschneck/centerline-width/main/data/doc_examples/river_coords_width_keep_intersections.png) | ![river_remove+png](https://raw.githubusercontent.com/cyschneck/centerline-width/main/data/doc_examples/river_coords_width_remove_intersections.png)| +**dark_mode** + +dark_mode will change the default Matplotlib background black and swap the centerline_color from black to white + +| dark_mode=False | dark_mode=True | +| ------------- | ------------- | +| ![river_white+png](https://raw.githubusercontent.com/cyschneck/centerline-width/main/data/doc_examples/river_coords_width_dark_mode_false.png) | ![river_black+png](https://raw.githubusercontent.com/cyschneck/centerline-width/main/data/doc_examples/river_coords_width_dark_mode_true.png)| + **coordinate_unit** Two options for measuring and displaying coordinates. The two options are "Decimal Degrees" and "Relative Distance". "Decimal Degrees" is the default option that uses the original data coordinate system with latitude/longitude. "Relative Distance" changes the coordinates of each point to be the distance (in meters) from the first point on the left bank diff --git a/centerline_width/error_handling.py b/centerline_width/error_handling.py index a7149a9..a18364f 100644 --- a/centerline_width/error_handling.py +++ b/centerline_width/error_handling.py @@ -38,6 +38,7 @@ def errorHandlingPlotCenterline(river_object=None, centerline_type=None, marker_type=None, centerline_color=None, + dark_mode=None, display_all_possible_paths=None, plot_title=None, save_plot_name=None, @@ -66,6 +67,9 @@ def errorHandlingPlotCenterline(river_object=None, if type(centerline_color) != str: raise ValueError(f"[centerline_color]: Must be a str, current type = '{type(centerline_color)}'") + if type(dark_mode) != bool: + raise ValueError(f"[dark_mode]: Must be a bool, current type = '{type(dark_mode)}'") + if type(display_all_possible_paths) != bool: raise ValueError(f"[display_all_possible_paths]: Must be a bool, current type = '{type(display_all_possible_paths)}'") @@ -93,6 +97,7 @@ def errorHandlingPlotCenterlineWidth(river_object=None, apply_smoothing=None, flag_intersections=None, remove_intersections=None, + dark_mode=None, coordinate_unit=None): # Error handling for plotCenterlineWidth() if river_object is None: @@ -126,6 +131,9 @@ def errorHandlingPlotCenterlineWidth(river_object=None, if type(remove_intersections) != bool: raise ValueError(f"[remove_intersections]: Must be a bool, current type = '{type(remove_intersections)}'") + if type(dark_mode) != bool: + raise ValueError(f"[dark_mode]: Must be a bool, current type = '{type(dark_mode)}'") + if type(coordinate_unit) != str: raise ValueError(f"[coordinate_unit]: Must be a str, current type = '{type(coordinate_unit)}'") else: diff --git a/centerline_width/plotDiagrams.py b/centerline_width/plotDiagrams.py index b54bacb..d3c2ffa 100644 --- a/centerline_width/plotDiagrams.py +++ b/centerline_width/plotDiagrams.py @@ -20,8 +20,18 @@ def plotCenterlineBackend(river_object=None, centerline_type="Voronoi", marker_type="line", centerline_color="black", + dark_mode=False, coordinate_unit=None): # Shared components between plotCenterline and plotCenterlineWidth + + # set plot to dark background and alternate centerline color default + if dark_mode: + plt.style.use('dark_background') + if centerline_color == "black": + centerline_color = "white" + if not dark_mode: + plt.style.use('default') # revert to white background + fig = plt.figure(figsize=(10,10)) ax = fig.add_subplot(111) scatter_plot_size = 4 @@ -58,7 +68,7 @@ def plotCenterlineBackend(river_object=None, centerline_type = centerline_type.title() marker_type = marker_type.title() - # Choose btween Decimal Degrees and Centerline Type + # Choose between Decimal Degrees and Centerline Type if centerline_type == "Voronoi": centerline_legend = "Voronoi Centerline Coordinates" if coordinate_unit == "Decimal Degrees": centerline_coordinates_by_type = river_object.centerlineVoronoi @@ -109,6 +119,7 @@ def plotCenterline(river_object=None, centerline_type="Voronoi", marker_type="line", centerline_color="black", + dark_mode=False, display_all_possible_paths=False, plot_title=None, save_plot_name=None, @@ -119,6 +130,7 @@ def plotCenterline(river_object=None, centerline_type=centerline_type, marker_type=marker_type, centerline_color=centerline_color, + dark_mode=dark_mode, display_all_possible_paths=display_all_possible_paths, plot_title=plot_title, save_plot_name=save_plot_name, @@ -130,6 +142,7 @@ def plotCenterline(river_object=None, centerline_type=centerline_type, marker_type=marker_type, centerline_color=centerline_color, + dark_mode=dark_mode, coordinate_unit=coordinate_unit) coordinate_unit = coordinate_unit.title() @@ -175,6 +188,7 @@ def plotCenterlineWidth(river_object=None, apply_smoothing=False, flag_intersections=True, remove_intersections=False, + dark_mode=False, coordinate_unit="Decimal Degrees"): # Plot Width Lines based on Centerline centerline_width.errorHandlingPlotCenterlineWidth(river_object=river_object, @@ -185,13 +199,16 @@ def plotCenterlineWidth(river_object=None, apply_smoothing=apply_smoothing, flag_intersections=flag_intersections, remove_intersections=remove_intersections, + dark_mode=dark_mode, coordinate_unit=coordinate_unit) + fig, ax, valid_path_through = plotCenterlineBackend(river_object=river_object, display_true_centerline=display_true_centerline, centerline_type="Voronoi", marker_type="line", centerline_color="black", + dark_mode=dark_mode, coordinate_unit=coordinate_unit) coordinate_unit = coordinate_unit.title() @@ -249,6 +266,7 @@ def plotCenterlineWidth(river_object=None, else: plt.plot(x_points, y_points, 'green', linewidth=1) else: + # display all width lines as green since flag_instersection=False if not valid_label_added: plt.plot(x_points, y_points, 'green', label="Width", linewidth=1) valid_label_added = True diff --git a/centerline_width/pytests/test_plotDiagrams.py b/centerline_width/pytests/test_plotDiagrams.py index a5f5aa7..467a62b 100644 --- a/centerline_width/pytests/test_plotDiagrams.py +++ b/centerline_width/pytests/test_plotDiagrams.py @@ -80,6 +80,12 @@ def test_plotCenterline_centerlineColorInvalidTypes(invalid_input, error_output) centerline_width.plotCenterline(river_object=river_class_example, centerline_color=invalid_input) +@pytest.mark.parametrize("invalid_input, error_output", invalid_non_bool_options) +def test_plotCenterline_darkModeInvalidTypes(invalid_input, error_output): + with pytest.raises(ValueError, match=re.escape("[dark_mode]: Must be a bool, current type = '{0}'".format(error_output))): + centerline_width.plotCenterline(river_object=river_class_example, + dark_mode=invalid_input) + @pytest.mark.parametrize("invalid_input, error_output", invalid_non_bool_options) def test_plotCenterline_displayAllPossiblePathsInvalidTypes(invalid_input, error_output): with pytest.raises(ValueError, match=re.escape("[display_all_possible_paths]: Must be a bool, current type = '{0}'".format(error_output))): @@ -167,6 +173,12 @@ def test_plotCenterlineWidth_removeIntersectionsInvalidTypes(invalid_input, erro centerline_width.plotCenterlineWidth(river_object=river_class_example, remove_intersections=invalid_input) +@pytest.mark.parametrize("invalid_input, error_output", invalid_non_bool_options) +def test_plotCenterlineWidth_darkModeInvalidTypes(invalid_input, error_output): + with pytest.raises(ValueError, match=re.escape("[dark_mode]: Must be a bool, current type = '{0}'".format(error_output))): + centerline_width.plotCenterlineWidth(river_object=river_class_example, + dark_mode=invalid_input) + def test_plotCenterlineWidth_coordinateUnitInvalidOption(): with pytest.raises(ValueError, match=re.escape("[coordinate_unit]: Must be an available option in ['Decimal Degrees', 'Relative Distance'], current option = 'Invalid Option'")): centerline_width.plotCenterlineWidth(river_object=river_class_example, diff --git a/centerline_width/riverCenterlineClass.py b/centerline_width/riverCenterlineClass.py index ab93b54..9889caf 100644 --- a/centerline_width/riverCenterlineClass.py +++ b/centerline_width/riverCenterlineClass.py @@ -107,6 +107,7 @@ def plotCenterline(self, centerline_type="Voronoi", marker_type="line", centerline_color="black", + dark_mode=False, display_all_possible_paths=False, plot_title=None, save_plot_name=None, @@ -116,6 +117,7 @@ def plotCenterline(self, centerline_type=centerline_type, marker_type=marker_type, centerline_color=centerline_color, + dark_mode=dark_mode, display_all_possible_paths=display_all_possible_paths, plot_title=plot_title, save_plot_name=save_plot_name, @@ -130,6 +132,7 @@ def plotCenterlineWidth(self, apply_smoothing=False, flag_intersections=True, remove_intersections=False, + dark_mode=False, coordinate_unit="Decimal Degrees"): centerline_width.plotCenterlineWidth(river_object=self, plot_title=plot_title, @@ -139,6 +142,7 @@ def plotCenterlineWidth(self, apply_smoothing=apply_smoothing, flag_intersections=flag_intersections, remove_intersections=remove_intersections, + dark_mode=dark_mode, coordinate_unit=coordinate_unit) def riverWidthFromCenterline(self, diff --git a/data/doc_examples/river_coords_width_dark_mode_false.png b/data/doc_examples/river_coords_width_dark_mode_false.png new file mode 100644 index 0000000..165763a Binary files /dev/null and b/data/doc_examples/river_coords_width_dark_mode_false.png differ diff --git a/data/doc_examples/river_coords_width_dark_mode_true.png b/data/doc_examples/river_coords_width_dark_mode_true.png new file mode 100644 index 0000000..3d9018f Binary files /dev/null and b/data/doc_examples/river_coords_width_dark_mode_true.png differ diff --git a/river_centerline_width_example.py b/river_centerline_width_example.py index 56db552..c144261 100644 --- a/river_centerline_width_example.py +++ b/river_centerline_width_example.py @@ -53,7 +53,7 @@ #coord_type = "relative DIStance" coord_type = "decimal degrees" - center_type = "Voronoi" + center_type = "VorOnoi" #river.saveCenterlineCSV(save_to_csv="centerline_for_csv.csv", centerline_type=center_type, coordinate_unit=coord_type) #river.saveCenterlineMAT(save_to_mat="centerline_for_matlab.mat", centerline_type=center_type, coordinate_unit=coord_type) @@ -65,9 +65,10 @@ centerline_type=center_type, marker_type="line", centerline_color="black", - display_all_possible_paths=True, + display_all_possible_paths=False, display_voronoi=False, plot_title=None, + dark_mode=True, coordinate_unit=coord_type) transect = 3 @@ -77,9 +78,10 @@ plot_title=None, display_true_centerline=True, transect_span_distance=transect, - apply_smoothing=True, + apply_smoothing=False, flag_intersections=True, remove_intersections=True, + dark_mode=True, coordinate_unit=coord_type) # Return width line for each centerline coordinates