From 19aa6ab34af0b0b1110e56a9c203e3b36d8ebfdb Mon Sep 17 00:00:00 2001 From: Yuksel-Rudy Date: Sun, 5 Oct 2025 17:18:30 -0600 Subject: [PATCH 1/2] A new feature to enable plot2d to show the line depth in 2D. This feature requires the updates in drawLine2d in subsystem.py in MoorPy to be integrated. - The user can provide a set value of maximum depth to show the most transparent part of the line. By default, this is set to the water depth. But sometimes, we might be interested in limiting the depth to the first 200m for instance or to show the depth of which it can be affected by marine growth (e.g., -170m). This is added as a variable in kwargs called max_line_depth. --- famodel/project.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/famodel/project.py b/famodel/project.py index a45091df..e1744f0d 100644 --- a/famodel/project.py +++ b/famodel/project.py @@ -2153,7 +2153,7 @@ def updatePositions(self): platform.r[1] = platform.body.r6[1] - def plot2d(self, ax=None, plot_seabed=False,draw_soil=False,plot_bathymetry=True, plot_boundary=True, bare=False, axis_equal=True,save=False,**kwargs): + def plot2d(self, ax=None, plot_seabed=False,draw_soil=False,plot_bathymetry=True, plot_boundary=True, color_lineDepth=False, bare=False, axis_equal=True,save=False,**kwargs): '''Plot aspects of the Project object in matplotlib in 3D. TODO - harmonize a lot of the seabed stuff with MoorPy System.plot... @@ -2182,6 +2182,7 @@ def plot2d(self, ax=None, plot_seabed=False,draw_soil=False,plot_bathymetry=True bath_levels = kwargs.get('bath_levels', None) show_legend = kwargs.get('show_legend', True) + max_line_depth = kwargs.get('max_line_depth', None) # max depth for line coloring if color_lineDepth is True # if axes not passed in, make a new figure if ax == None: @@ -2250,6 +2251,17 @@ def plot2d(self, ax=None, plot_seabed=False,draw_soil=False,plot_bathymetry=True ax.fill(env['x'], env['y'], edgecolor=edgecolor, facecolor='none', linestyle='dashed', lw=0.8, label='Platform Envelope') if plot_moorings: + depth_cmap_settings = None + if color_lineDepth: + if max_line_depth is None: + bath_depth = True + if plot_bathymetry: + raise ValueError("Cannot use depth-based line coloring with plot_bathymetry=True. Disable bathymetry to avoid confusion.") + depth_cmap_settings = { + "cmap": "Blues", + "vmin": max_line_depth if max_line_depth else -np.max(self.grid_depth), + "vmax": 0 + } for mooring in self.mooringList.values(): for name, env in mooring.envelopes.items(): #if 'shape' in env: # if there's a shapely object @@ -2284,16 +2296,27 @@ def plot2d(self, ax=None, plot_seabed=False,draw_soil=False,plot_bathymetry=True if mooring.ss: mooring.ss.drawLine2d(0, ax, color="self", endpoints=False, - Xuvec=[1,0,0], Yuvec=[0,1,0],label=labs) + Xuvec=[1,0,0], Yuvec=[0,1,0], depth_cmap_settings=depth_cmap_settings, label=labs) elif mooring.parallels: for i,line in enumerate(lineList): line.drawLine2d(0, ax, color="self", - Xuvec=[1,0,0], Yuvec=[0,1,0],label=labs[i]) + Xuvec=[1,0,0], Yuvec=[0,1,0], depth_cmap_settings=depth_cmap_settings, label=labs[i]) else: # simple line plot ax.plot([mooring.rA[0], mooring.rB[0]], [mooring.rA[1], mooring.rB[1]], 'k', lw=0.5, label='Mooring Line') - + + # ---- Add colorbar for line depth ---- + if depth_cmap_settings is not None and not bare: + import matplotlib.cm as cm + import matplotlib.colors as mcolors + sm = cm.ScalarMappable(cmap=cm.get_cmap(depth_cmap_settings["cmap"]), + norm=mcolors.Normalize(vmin=depth_cmap_settings["vmin"], + vmax=depth_cmap_settings["vmax"])) + sm.set_array([]) + cbar = plt.colorbar(sm, ax=ax, fraction=0.04) + cbar.set_label("Line Depth (m)") + if plot_anchors: for anchor in self.anchorList.values(): ax.plot(anchor.r[0],anchor.r[1], 'mo',ms=2, label='Anchor') From 0b73ab7f92dea2ff99f3459043bb58f38dead800 Mon Sep 17 00:00:00 2001 From: Yuksel-Rudy Date: Mon, 6 Oct 2025 12:08:26 -0600 Subject: [PATCH 2/2] enhancing plot2d feature to color lines based on their depth in the water column: - adding an option to only plot the line color based on depth for shared lines. --- famodel/project.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/famodel/project.py b/famodel/project.py index e1744f0d..5a890802 100644 --- a/famodel/project.py +++ b/famodel/project.py @@ -2163,6 +2163,8 @@ def plot2d(self, ax=None, plot_seabed=False,draw_soil=False,plot_bathymetry=True ... bare : bool If True, supress display of extra labeling like the colorbar. + color_lineDepth: bool + If True, color mooring lines based on depth. Only works if plot_bathymetry=False. ''' # Handle extra keyword arguments or use default values @@ -2183,7 +2185,7 @@ def plot2d(self, ax=None, plot_seabed=False,draw_soil=False,plot_bathymetry=True show_legend = kwargs.get('show_legend', True) max_line_depth = kwargs.get('max_line_depth', None) # max depth for line coloring if color_lineDepth is True - + only_shared = kwargs.get('only_shared', False) # if color_lineDepth is True, only color shared lines # if axes not passed in, make a new figure if ax == None: fig, ax = plt.subplots(1,1, figsize=figsize) @@ -2251,16 +2253,15 @@ def plot2d(self, ax=None, plot_seabed=False,draw_soil=False,plot_bathymetry=True ax.fill(env['x'], env['y'], edgecolor=edgecolor, facecolor='none', linestyle='dashed', lw=0.8, label='Platform Envelope') if plot_moorings: - depth_cmap_settings = None + line_depth_settings = None if color_lineDepth: - if max_line_depth is None: - bath_depth = True if plot_bathymetry: raise ValueError("Cannot use depth-based line coloring with plot_bathymetry=True. Disable bathymetry to avoid confusion.") - depth_cmap_settings = { + line_depth_settings = { "cmap": "Blues", "vmin": max_line_depth if max_line_depth else -np.max(self.grid_depth), - "vmax": 0 + "vmax": 0, + "only_shared": only_shared } for mooring in self.mooringList.values(): for name, env in mooring.envelopes.items(): @@ -2296,23 +2297,23 @@ def plot2d(self, ax=None, plot_seabed=False,draw_soil=False,plot_bathymetry=True if mooring.ss: mooring.ss.drawLine2d(0, ax, color="self", endpoints=False, - Xuvec=[1,0,0], Yuvec=[0,1,0], depth_cmap_settings=depth_cmap_settings, label=labs) + Xuvec=[1,0,0], Yuvec=[0,1,0], line_depth_settings=line_depth_settings, label=labs) elif mooring.parallels: for i,line in enumerate(lineList): line.drawLine2d(0, ax, color="self", - Xuvec=[1,0,0], Yuvec=[0,1,0], depth_cmap_settings=depth_cmap_settings, label=labs[i]) + Xuvec=[1,0,0], Yuvec=[0,1,0], line_depth_settings=line_depth_settings, label=labs[i]) else: # simple line plot ax.plot([mooring.rA[0], mooring.rB[0]], [mooring.rA[1], mooring.rB[1]], 'k', lw=0.5, label='Mooring Line') # ---- Add colorbar for line depth ---- - if depth_cmap_settings is not None and not bare: + if line_depth_settings is not None and not bare: import matplotlib.cm as cm import matplotlib.colors as mcolors - sm = cm.ScalarMappable(cmap=cm.get_cmap(depth_cmap_settings["cmap"]), - norm=mcolors.Normalize(vmin=depth_cmap_settings["vmin"], - vmax=depth_cmap_settings["vmax"])) + sm = cm.ScalarMappable(cmap=cm.get_cmap(line_depth_settings["cmap"]), + norm=mcolors.Normalize(vmin=line_depth_settings["vmin"], + vmax=line_depth_settings["vmax"])) sm.set_array([]) cbar = plt.colorbar(sm, ax=ax, fraction=0.04) cbar.set_label("Line Depth (m)")