groundhog.general.plotting — Groundhog 0.12.0 documentation (2024)

#!/usr/bin/env python# -*- coding: utf-8 -*-__author__ = 'Bruno Stuyts'# Native Python packagesimport datetimeimport warningsimport traceback# 3rd party packagesfrom jinja2 import Environment, BaseLoaderimport plotly.graph_objs as gofrom plotly.colors import DEFAULT_PLOTLY_COLORSfrom plotly import subplotsimport numpy as npimport matplotlib.pyplot as plt# Project importsGROUNDHOG_PLOTTING_CONFIG = { 'showLink': True, 'plotlyServerURL': "https://github.com/snakesonabrain/groundhog", 'linkText': 'Created by groundhog using Plotly!'}PLOTLY_GLOBAL_FONT = dict(family='Century Gothic', size=12, color='#5f5f5f')C0 = '#1f77b4'; C1 = '#ff7f0e'; C2 = '#2ca02c'; C3 = '#d62728'; C4 = '#9467bd'; C5 = '#8c564b'; C6 = '#e377c2'; C7 = '#7f7f7f'; C8 = '#bcbd22'; C9 = '#17becf'PLOTLY_COLORS = [C0, C1, C2, C3, C4, C5, C6, C7, C8, C9]BRIGHTCOLORS = ['#4477AA', '#EE6677', '#228833', '#CCBB44', '#66CCEE', '#AA3377', '#BBBBBB']USCS_HATCHES = { 'SW': '..', 'SP': '....', 'SM': '||...', 'SC': '///...', 'ML': '||||', 'CL': '////', 'OL': '--', 'MH': '||', 'CH': '//'}

[docs]def plot_with_log(x=[[],], z=[[],], names=[[],], showlegends=None, hide_all_legends=False, modes=None, markerformats=None, soildata=None, fillcolordict={'SAND': 'yellow', 'CLAY': 'brown', 'SILT': 'green', 'ROCK': 'grey'}, depth_from_key="Depth from [m]", depth_to_key="Depth to [m]", colors=None, logwidth=0.05, xtitles=[], ztitle=None, xranges=None, zrange=None, ztick=None, dticks=None, layout=dict(), showfig=True): """ Plots a given number of traces in a plot with a soil mini-log on the left hand side. The traces are given as a list of lists, the traces are grouped per plotting panel. For example x=[[np.linspace(0, 1, 100), np.logspace(0,2,100)], [np.linspace(1, 3, 100), ]] leads to the first two traces plotted in the first panel and one trace in the second panel. The same goes for the z arrays, trace names, ... :param x: List of lists of x-arrays for the traces :param z: List of lists of z-arrays for the traces :param names: List of lists of names for the traces (used in legend) :param showlegends: Array of booleans determining whether or not to show the trace in the legend. Showing/hiding legends can be specified per trace. :param hide_all_legends: Boolean indicating whether all legends need to be hidden (default=False). :param modes: List of display modes for the traces (select from 'lines', 'markers' or 'lines+markers' :param markerformats: List of formats for the markers (see Plotly docs for more info) :param soildata: Pandas dataframe with keys 'Soil type': Array with soil type for each layer, 'Depth from [m]': Array with start depth for each layer, 'Depth to [m]': Array with bottom depth for each layer :param fillcolordict: Dictionary with fill colours (default yellow for 'SAND', brown from 'CLAY' and grey for 'ROCK') :param depth_from_key: Key for the column with start depths of each layer :param depth_to_key: Key for the column with end depths of each layer :param colors: List of colours to be used for plotting (default = default Plotly colours) :param logwidth: Width of the soil width as a ratio of the total plot with (default = 0.05) :param xtitles: Array with X-axis titles for the panels :param ztitle: Depth axis title (Depth axis is shared between all panels) :param xranges: List with ranges to be used for X-axes :param zrange: Range to be used for Y-axis :param ztick: Tick interval to be used for the Y-axis :param dticks: List of tick intervals to be used for the X-axes :param layout: Dictionary with the layout settings :param showfig: Boolean determining whether the figure needs to be shown :return: Plotly figure object which can be further modified """ no_panels = x.__len__() panel_widths = list(map(lambda _x: (1 - logwidth) / no_panels, x)) panel_widths = list(np.append(logwidth, panel_widths)) _fig = subplots.make_subplots(rows=1, cols=no_panels + 1, column_widths=panel_widths, shared_yaxes=True, print_grid=False) _showlegends = [] _modes = [] _markerformats = [] _colors = [] for i, _x in enumerate(x): _showlegends_panel = [] _modes_panel = [] _markerformats_panel = [] _colors_panel = [] for j, _trace_x in enumerate(_x): _showlegends_panel.append(not(hide_all_legends)) _modes_panel.append('lines') _markerformats_panel.append(dict(size=5)) _colors_panel.append(DEFAULT_PLOTLY_COLORS[j]) _showlegends.append(_showlegends_panel) _modes.append(_modes_panel) _markerformats.append(_markerformats_panel) _colors.append(_colors_panel) if showlegends is None: showlegends = _showlegends if modes is None: modes = _modes if markerformats is None: markerformats = _markerformats if colors is None: colors = _colors _traces = [] log_dummy_trace = go.Scatter(x=[0, 1], y=[np.nan, np.nan], showlegend=False) _fig.append_trace(log_dummy_trace, 1, 1) for i, _x in enumerate(x): for j, _trace_x in enumerate(_x): try: _trace = go.Scatter( x=x[i][j], y=z[i][j], mode=modes[i][j], name=names[i][j], showlegend=showlegends[i][j], marker=markerformats[i][j], line=dict(color=colors[i][j])) _fig.append_trace(_trace, 1, i + 2) except Exception as err: warnings.warn( "Error during traces creation for trace %s - %s" % (names[i][j], str(traceback.format_exc()))) _layers = [] for i, row in soildata.iterrows(): _fillcolor = fillcolordict[row['Soil type']] _y0 = row[depth_from_key] _y1 = row[depth_to_key] _layers.append( dict(type='rect', xref='x1', yref='y', x0=0, y0=_y0, x1=1, y1=_y1, fillcolor=_fillcolor, opacity=1)) if zrange is None: _fig['layout']['yaxis1'].update(title=ztitle, autorange='reversed') else: _fig['layout']['yaxis1'].update(title=ztitle, range=zrange) _fig['layout'].update(layout) _fig['layout'].update(shapes=_layers) if ztick is not None: _fig['layout']['yaxis1'].update(dtick=ztick) _fig['layout']['xaxis1'].update( anchor='y', title=None, side='top', tickvals=[]) for i, _x in enumerate(x): _fig['layout']['xaxis%i' % (i + 2)].update( anchor='y', title=xtitles[i], side='top') if dticks is not None: _fig['layout']['xaxis%i' % (i + 2)].update(dtick=dticks[i]) if xranges is not None: _fig['layout']['xaxis%i' % (i + 2)].update(range=xranges[i]) if showfig: _fig.show(config=GROUNDHOG_PLOTTING_CONFIG) return _fig

[docs]class LogPlot(object): """ Class for planneled plots with a minilog on the side. """ def __init__(self, soilprofile, no_panels=1, logwidth=0.05, fillcolordict={"Sand": 'yellow', "Clay": 'brown', 'Rock': 'grey'}, soiltypelegend=True, soiltypecolumn="Soil type", line_width=1, **kwargs): """ Initializes a figure with a minilog on the side. :param soilprofile: Soilprofile used for the minilog :param no_panels: Number of panels :param logwidth: Width of the minilog as a ratio to the total width of the figure (default=0.05) :param fillcolordict: Dictionary with fill colors for each of the soil types. Every unique ``Soil type`` needs to have a corresponding color. Default: ``{"Sand": 'yellow', "Clay": 'brown', 'Rock': 'grey'}`` :param soiltypelegend: Boolean determining whether legend entries need to be shown for the soil types in the log :param soiltypecolumn: Column name used to identify the soil type. The entries in this column need to correspond to keys in ``fillcolordict`` :param line_width: Line width for the boundary between layers :param kwargs: Optional keyword arguments for the make_subplots method """ self.soilprofile = soilprofile # Determine the panel widths panel_widths = list(map(lambda _x: (1 - logwidth) / no_panels, range(0, no_panels))) panel_widths = list(np.append(logwidth, panel_widths)) # Set up the figure self.fig = subplots.make_subplots( rows=1, cols=no_panels+1, column_widths=panel_widths, shared_yaxes=True, print_grid=False, **kwargs) self.fig['layout']['yaxis1'].update(range=(soilprofile.max_depth, soilprofile.min_depth)) # Create rectangles for the log plot _layers = [] for i, row in soilprofile.iterrows(): try: _fillcolor = fillcolordict[row[soiltypecolumn]] except: _fillcolor = DEFAULT_PLOTLY_COLORS[i % 10] _y0 = row[self.soilprofile.depth_from_col] _y1 = row[self.soilprofile.depth_to_col] _layers.append( dict(type='rect', xref='x1', yref='y', x0=0, y0=_y0, x1=1, y1=_y1, fillcolor=_fillcolor, opacity=1, line_width=line_width)) for _soiltype in soilprofile[soiltypecolumn].unique(): try: _fillcolor = fillcolordict[_soiltype] except: soiltypelegend = False try: if soiltypelegend: _trace = go.Bar( x=[-10, -10], y=[row['Depth to [m]'], row['Depth to [m]']], name=_soiltype, marker=dict(color=_fillcolor)) self.fig.append_trace(_trace, 1, 1) except: pass self.fig['layout'].update(shapes=_layers) self.fig['layout']['xaxis1'].update( anchor='y', title=None, side='top', tickvals=[], range=(0, 1)) self.fig['layout']['yaxis1'].update(title='Depth [m]') for i in range(0, no_panels): _dummy_data = go.Scatter( x=[0, 100], y=[np.nan, np.nan], mode='lines', name='Dummy', showlegend=False, line=dict(color='black')) self.fig.append_trace(_dummy_data, 1, i + 2) self.fig['layout']['xaxis%i' % (i + 2)].update( anchor='y', title='X-axis %i' % (i+1), side='top')

[docs] def add_trace(self, x, z, name, panel_no, resetaxisrange=False, **kwargs): """ Adds a trace to the plot. By default, lines are added but optional keyword arguments can be added for go.Scatter as ``**kwargs`` :param x: Array with the x-values :param z: Array with the z-values :param name: Name for the trace (LaTeX allowed, e.g. ``r'$ \\alpha $'``) :param panel_no: Panel to plot the trace on (1-indexed) :param resetaxisrange: Boolean determining whether the axis range needs to be reset to fit this trace :param kwargs: Optional keyword arguments for the ``go.Scatter`` constructor :return: Adds the trace to the specified panel """ try: mode = kwargs['mode'] kwargs.pop('mode') except: mode = 'lines' _data = go.Scatter( x=x, y=z, mode=mode, name=name, **kwargs) self.fig.append_trace(_data, 1, panel_no + 1) if resetaxisrange: self.fig['layout']['xaxis%i' % (panel_no + 1)].update( range=(np.array(x).min(), np.array(x).max()))

[docs] def add_soilparameter_trace(self, parametername, panel_no, legendname=None, resetaxisrange=False, **kwargs): """ Adds a trace to the plot based on a soil parameter available in the SoilProfile. By default, lines are added but optional keyword arguments can be added for go.Scatter as ``**kwargs`` :param parametername: Name of the soil parameter (with units) e.g. ``'Su [kPa]'`` when ``'Su from [kPa]'`` and ``'Su to [kPa]'`` are available in the SoilProfile :param panel_no: Panel to plot the trace on (1-indexed) :param legendname: Name for the trace (LaTeX allowed, e.g. ``r'$ \\alpha $'``), default is None to use ``parametername`` :param resetaxisrange: Boolean determining whether the axis range needs to be reset to fit this trace :param kwargs: Optional keyword arguments for the ``go.Scatter`` constructor :return: Adds the trace to the specified panel """ if not parametername in self.soilprofile.soil_parameters(): raise ValueError("Soil parameter %s not encoded in the soil profile. Check soil profile definition and try again" % parametername) x = self.soilprofile.soilparameter_series(parametername)[1] z = self.soilprofile.soilparameter_series(parametername)[0] if legendname is not None: name = legendname else: name = parametername self.add_trace(x, z, name, panel_no, resetaxisrange, **kwargs)

[docs] def set_xaxis(self, title, panel_no, **kwargs): """ Changes the X-axis title of a panel :param title: Title to be set (LaTeX allowed, e.g. ``r'$ \alpha $'``) :param panel_no: Panel number (1-indexed) :param kwargs: Additional keyword arguments for the axis layout update function, e.g. ``range=(0, 100)`` :return: Adjusts the X-axis of the specified panel """ self.fig['layout']['xaxis%i' % (panel_no + 1)].update( title=title, **kwargs)

[docs] def set_zaxis(self, title, **kwargs): """ Changes the Z-axis :param title: Title to be set (LaTeX allowed, e.g. ``r'$ \alpha $'``) :param kwargs: Additional keyword arguments for the axis layout update function, e.g. ``range=(0, 100)`` :return: Adjusts the Z-axis """ self.fig['layout']['yaxis1'].update( title=title, **kwargs)

[docs] def set_size(self, width, height): """ Adjust the size of the plot :param width: Width of the plot in pixels :param height: Height of the plot in pixels :return: Adjust the height and width as specified """ self.fig['layout'].update(height=height, width=width)

[docs] def set_title(self, title): """ Set a title for the plot :param title: Title for the plot :return: Sets the title as specified """ self.fig['layout'].update(title=title)

def show(self): self.fig.show(config=GROUNDHOG_PLOTTING_CONFIG)

[docs]class LogPlotMatplotlib(object): """ Class for planneled plots with a minilog on the side, using the Matplotlib plotting backend """ def __init__(self, soilprofile, no_panels=1, logwidth=0.05, fillcolordict={"Sand": 'yellow', "Clay": 'brown', 'Rock': 'grey', 'Silt': 'green'}, hatchpatterns={"Sand": "...", "Clay": '////', 'Rock':'oo', 'Silt': '|||'}, soiltypelegend=True, soiltypecolumn='Soil type', edgecolor='black', figheight=6, plot_layer_transitions=True, showgrid=True, **kwargs): """ Initializes a figure with a minilog on the side. :param soilprofile: Soilprofile used for the minilog :param no_panels: Number of panels :param logwidth: Width of the minilog as a percentage of the total width (default=0.05) :param fillcolordict: Dictionary with fill colors for each of the soil types. Every unique ``Soil type`` needs to have a corresponding color. Default: ``{"Sand": 'yellow', "Clay": 'brown', 'Rock': 'grey'}`` :param hatchpatterns: Matplotlib letters used for hatching of the soil types :param soiltypelegend: Boolean determining whether legend entries need to be shown for the soil types in the log :param soiltypecolumn: Column name used to identify the soil type. The entries in this column need to correspond to keys in ``fillcolordict`` :param edgecolor: Color of the edge of a layer :param figheight: Figure height in inches (default=6in) :param plot_layer_transitions: Boolean determining whether layer transitions need to be plotted or not :param showgrid: Boolean determining whether a grid is shown on the plot panels or not (default=True) :param kwargs: Optional keyword arguments for the make_subplots method """ self.soilprofile = soilprofile self.no_panels = no_panels # Determine the panel widths panel_widths = list(map(lambda _x: (1 - logwidth) / no_panels, range(0, no_panels))) panel_widths = list(np.append(logwidth, panel_widths)) # Set up the figure self.fig, self.axes = plt.subplots(1, no_panels + 1, figsize=(4 * no_panels, figheight), sharex=False, sharey=True, constrained_layout=False, gridspec_kw={'width_ratios': panel_widths}) self.axes[0].set_ylim([soilprofile.max_depth, soilprofile.min_depth]) # Create rectangles for the log plot _layers = [] _color_assignment = dict() for i, row in soilprofile.iterrows(): try: _fillcolor = fillcolordict[row[soiltypecolumn]] _color_assignment[row[soiltypecolumn]] = _fillcolor except: if row[soiltypecolumn] in _color_assignment.keys(): _fillcolor = _color_assignment[row[soiltypecolumn]] else: _fillcolor = BRIGHTCOLORS[i % 7] _color_assignment[row[soiltypecolumn]] = _fillcolor try: _hatch = hatchpatterns[row[soiltypecolumn]] except: _hatch = None _y0 = row[self.soilprofile.depth_from_col] _y1 = row[self.soilprofile.depth_to_col] self.axes[0].fill( [0.0,0.0,1.0,1.0],[_y0, _y1, _y1, _y0], fill=True, color=_fillcolor, label='_nolegend_', edgecolor=edgecolor, hatch=_hatch) _legend_handles = [] for _soiltype in soilprofile[soiltypecolumn].unique(): try: _fillcolor = _color_assignment[_soiltype] except: soiltypelegend = False try: if soiltypelegend: _legend_entry, = self.axes[0].fill( [-11.0,-11.0,-10.0,-10.0],[_y0, _y1, _y1, _y0], fill=True, color=_fillcolor, label=_soiltype, edgecolor=edgecolor) _legend_handles.append(_legend_entry) except: pass self._legend_entries = _legend_handles self.axes[0].set_xlim([0, 1]) self.axes[0].get_xaxis().set_ticks([]) self.axes[0].set_ylabel('Depth below mudline [m]',size=15) for i in range(0, no_panels): _dummy_data = self.axes[i+1].plot([0, 100], [np.nan, np.nan], label='_nolegend_') self.axes[i+1].tick_params(labelbottom=False,labeltop=True) self.axes[i+1].set_xlabel('X-axis %i' % (i + 1), size=15) self.axes[i+1].xaxis.set_label_position('top') self.axes[i+1].set_xlim([0, 1]) self.axes[i+1].set_ylim([soilprofile.max_depth, soilprofile.min_depth]) self.plot_layer_transitions = plot_layer_transitions if showgrid: for i in range(0, no_panels): self.axes[i+1].grid() else: pass

[docs] def add_trace(self, x, z, name, panel_no, resetaxisrange=False, line=True, showlegend=False, **kwargs): """ Adds a trace to the plot. By default, lines are added but optional keyword arguments can be added for plt.plot as ``**kwargs`` :param x: Array with the x-values :param z: Array with the z-values :param name: Label for the trace (LaTeX allowed, e.g. ``r'$ \alpha $'``) :param panel_no: Panel to plot the trace on (1-indexed) :param resetaxisrange: Boolean determining whether the axis range needs to be reset to fit this trace :param line: Boolean determining whether the data needs to be shown as a line or as individual markers :param showlegend: Boolean determining whether the trace name needs to be added to the legend entries :param kwargs: Optional keyword arguments for the ``go.Scatter`` constructor :return: Adds the trace to the specified panel """ if line: _axes_obj = self.axes[panel_no].plot(x, z,label=name, **kwargs) else: _axes_obj = self.axes[panel_no].scatter(x, z,label=name, **kwargs) if resetaxisrange: self.axes[panel_no].set_xlim([x[~np.isnan(x)].min(), x[~np.isnan(x)].max()]) if showlegend: if line: self._legend_entries.append(_axes_obj[0]) else: self._legend_entries.append(_axes_obj)

[docs] def add_soilparameter_trace(self, parametername, panel_no, legendname=None, resetaxisrange=False, line=True, showlegend=False, **kwargs): """ Adds a trace to the plot based on a soil parameter available in the SoilProfile. By default, lines are added but optional keyword arguments can be added for plt.plot as ``**kwargs`` :param parametername: Name of the soil parameter (with units) e.g. ``'Su [kPa]'`` when ``'Su from [kPa]'`` and ``'Su to [kPa]'`` are available in the SoilProfile :param panel_no: Panel to plot the trace on (1-indexed) :param legendname: Label for the trace (LaTeX allowed, e.g. ``r'$ \\alpha $'``) :param resetaxisrange: Boolean determining whether the axis range needs to be reset to fit this trace :param line: Boolean determining whether the data needs to be shown as a line or as individual markers :param showlegend: Boolean determining whether the trace name needs to be added to the legend entries :param kwargs: Optional keyword arguments for the ``go.Scatter`` constructor :return: Adds the trace to the specified panel """ if not parametername in self.soilprofile.soil_parameters(): raise ValueError("Soil parameter %s not encoded in the soil profile. Check soil profile definition and try again" % parametername) x = self.soilprofile.soilparameter_series(parametername)[1] z = self.soilprofile.soilparameter_series(parametername)[0] if legendname is not None: name = legendname else: name = parametername self.add_trace(x, z, name, panel_no, resetaxisrange, line, showlegend, **kwargs)

[docs] def set_xaxis_title(self, title, panel_no, size=15, **kwargs): """ Changes the X-axis title of a panel :param title: Title to be set (LaTeX allowed, e.g. ``r'$ \alpha $'``) :param panel_no: Panel number (1-indexed) :param kwargs: Additional keyword arguments for the axis layout update function, e.g. ``range=(0, 100)`` :return: Adjusts the X-axis of the specified panel """ self.axes[panel_no].set_xlabel(title, size=size)

[docs] def set_xaxis_range(self, min_value, max_value, panel_no, ticks=None, **kwargs): """ Changes the X-axis range of a panel :param min_value: Minimum value of the plot panel range :param max_value: Maximum value of the plot panel range :param panel_no: Panel number (1-indexed) :param ticks: List of ticks to set (default=None for Matplotlib defaults) :param kwargs: Additional keyword arguments for the ``set_xlim`` method :return: Adjusts the X-axis range of the specified panel """ self.axes[panel_no].set_xlim([min_value, max_value]) if ticks is not None: self.axes[panel_no].set_xticks(ticks)

[docs] def set_zaxis_title(self, title, size=15, **kwargs): """ Changes the Z-axis :param title: Title to be set (LaTeX allowed, e.g. ``r'$ \alpha $'``) :param kwargs: Additional keyword arguments for the ``set_label`` method :return: Adjusts the Z-axis title """ self.axes[0].set_ylabel(title, size=size)

[docs] def set_zaxis_range(self, min_depth, max_depth, ticks=None, **kwargs): """ Changes the Z-axis :param min_depth: Minimum depth of the plot :param max_depth: Maximum depth of the plot :param ticks: List of ticks to set (default=None for Matplotlib defaults) :param kwargs: Additional keyword arguments for the ``set_ylim`` method :return: Adjusts the Z-axis range """ self.axes[0].set_ylim([max_depth, min_depth]) if ticks is not None: self.axes[0].set_yticks(ticks)

[docs] def set_size(self, width, height): """ Adjust the size of the plot :param width: Width of the plot in inches :param height: Height of the plot in inches :return: Adjust the height and width as specified """ plt.gcf().set_size_inches(width, height)

def show_legend(self): plt.legend(handles=self._legend_entries, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.) def plot_layers(self): for i in range(0, self.no_panels): for _y in self.soilprofile.layer_transitions(): self.axes[i+1].plot( self.axes[i+1].get_xlim(), (_y, _y), color='grey', ls="--" ) def show(self, showlegend=True, showfig=True): if self.plot_layer_transitions: self.plot_layers() else: pass if showlegend: self.show_legend() else: pass if showfig: plt.show() else: pass

[docs] def save_fig(self, path, dpi=250, bbox_inches='tight',pad_inches=1): """ Exports the figure to png format :param path: Path of the figure (filename ends in .png) :param dpi: Output resolution :param bbox_inches: Setting for the bounding box :param pad_inches: Inches for padding """ plt.savefig(path, dpi=dpi,bbox_inches=bbox_inches, pad_inches=pad_inches)

[docs] def select_additional_layers(self, no_additional_layers, panel_no=1, precision=2): """ Allows for the selection of additional layer transitions for the ``SoilProfile`` object. The number of additional transition is controlled by the ``no_additional_layers`` argument. Click on the desired layer transition location in the specified panel (default ``panel_no=1``) The depth of the layer transition is rounded according to the ``precision`` argument. Default=2 for cm accuracy.""" ax = self.axes[panel_no] xy = plt.ginput(no_additional_layers) x = [p[0] for p in xy] y = [round(p[1], precision) for p in xy] for _y in y: for i in range(self.axes.__len__() - 1): line = self.axes[i+1].plot( self.axes[i+1].get_xlim(), (_y, _y), color='grey', ls="--") self.soilprofile.insert_layer_transition(_y) ax.figure.canvas.draw()

[docs] def select_layering(self, panel_no=1, precision=2, stop_threshold=0): """ Allows for the selection of layer transitions for the ``SoilProfile`` object. The number of additional transition is controlled by how often the user clicks. Click on the desired layer transition location in the specified panel (default ``panel_no=1``). The selection stops when the user clicks on a point with x-coordinate below the ``stop_threshold``. The depth of the layer transition is rounded according to the ``precision`` argument. Default=2 for cm accuracy.""" ax = self.axes[panel_no] final = False while not final: xy = plt.ginput(1) x = [p[0] for p in xy] y = [round(p[1], precision) for p in xy] if x[0] < stop_threshold: final = True else: for _y in y: for i in range(self.axes.__len__() - 1): line = self.axes[i+1].plot( self.axes[i+1].get_xlim(), (_y, _y), color='grey', ls="--") self.soilprofile.insert_layer_transition(_y) ax.figure.canvas.draw()

[docs] def select_constant(self, panel_no, parametername, units, nan_tolerance=0.1): """ Selects a constant value in each layer. Click the desired value in each layer, working from the top down. If a nan value needs to be set in a layer, click sufficiently close to the minimum of the x axis. The ``nan_tolerance`` argument determines which values are interpreted as nan. The parameter is added to the ``SoilProfile`` object with the ``'parametername [units]'`` key. """ ax = self.axes[panel_no] xy = plt.ginput(self.soilprofile.__len__()) x = [p[0] for p in xy] y = [p[1] for p in xy] for i, _x in enumerate(x): if _x < nan_tolerance: x[i] = np.nan self.soilprofile["%s [%s]" % (parametername, units)] = x self.add_soilparameter_trace( parametername="%s [%s]" % (parametername, units), panel_no=panel_no) ax.figure.canvas.draw()

[docs] def select_linear(self, panel_no, parametername, units, nan_tolerance=0.1): """ Selects a linear variation in each layer. Click the desired value at each layer boundary. Note that a value needs to be selected at the top and bottom of each layer (2 x no layers clicks). If a nan value needs to be set in a layer, click sufficiently close to the minimum of the x axis. The ``nan_tolerance`` argument determines which values are interpreted as nan. The parameter is added to the ``SoilProfile`` object with the ``'parametername [units]'`` key. """ ax = self.axes[panel_no] xy = plt.ginput(2 * self.soilprofile.__len__()) x = [p[0] for p in xy] y = [p[1] for p in xy] for i, _x in enumerate(x): if _x < nan_tolerance: x[i] = np.nan self.soilprofile["%s from [%s]" % (parametername, units)] = x[::2] self.soilprofile["%s to [%s]" % (parametername, units)] = x[1::2] self.add_soilparameter_trace( parametername="%s [%s]" % (parametername, units), panel_no=panel_no) ax.figure.canvas.draw()

[docs]def peak_picker(x, y, correct_selected_point=True): """ Generates an interactive Matplotlib plot which allows you to pick the peak from a graph with e.g. load-displacement data :param x: Array with x-values :param y: Array with y-values :param correct_selected_point: Boolean determining whether a correction is applied to interpolate the peak based on the selected value of X for the peak :returns: Dictionary with the following keys: - 'x100': x-coordinate of the peak - 'y100': y-coordinate of the peak - 'x50': x-coordinate where y reached 50% of its peak y - 'y50': y-coordinate with y equal to 50% of the peak y """ # Coerce to Numpy arrays x = np.array(x) y = np.array(y) # Close all open figures plt.close('all') # Generate the figure for peak picking plt.figure(1, figsize=(8,12)) plt.plot(x, y) plt.xlabel('$ x $', size=15) plt.ylabel('$ y $', size=15) # Click on the peak xy = plt.ginput(1) # Calculate derived quantities x100 = xy[0][0] if correct_selected_point: y100 = np.interp(x100, x, y) else: y100 = xy[0][1] prepeak_x = x[np.where(x <= x100)] prepeak_y = y[np.where(x <= x100)] y50 = 0.5 * y100 x50 = np.interp(y50, prepeak_y, prepeak_x) plt.scatter([x50, x100], [y50, y100], c='red') return { 'x100': x100, 'y100': y100, 'x50': x50, 'y50': y50, 'plot': plt.gcf() }

groundhog.general.plotting — Groundhog 0.12.0 documentation (2024)

References

Top Articles
Mike's Zesty Three Bean Salad Recipe
Peanut Butter Ice Cream Recipe- Just 3 Ingredients!
1970 Chevelle Ss For Sale Craigslist
La connexion à Mon Compte
My Boyfriend Has No Money And I Pay For Everything
Jennette Mccurdy And Joe Tmz Photos
How Much Is 10000 Nickels
Richard Sambade Obituary
Marist Dining Hall Menu
Needle Nose Peterbilt For Sale Craigslist
Obituary Times Herald Record
Planets Visible Tonight Virginia
What Does Dwb Mean In Instagram
Brutál jó vegán torta! – Kókusz-málna-csoki trió
Med First James City
I Wanna Dance with Somebody : séances à Paris et en Île-de-France - L'Officiel des spectacles
Navy Female Prt Standards 30 34
Skyward Login Jennings County
Clear Fork Progress Book
Craigslist Red Wing Mn
Craigslist Pinellas County Rentals
ELT Concourse Delta: preparing for Module Two
Concordia Apartment 34 Tarkov
Heart Ring Worth Aj
Jail View Sumter
11 Ways to Sell a Car on Craigslist - wikiHow
Yugen Manga Jinx Cap 19
Chamberlain College of Nursing | Tuition & Acceptance Rates 2024
Airline Reception Meaning
480-467-2273
Ficoforum
A Man Called Otto Showtimes Near Carolina Mall Cinema
Gus Floribama Shore Drugs
The Latest: Trump addresses apparent assassination attempt on X
Six Flags Employee Pay Stubs
Weekly Math Review Q2 7 Answer Key
The Attleboro Sun Chronicle Obituaries
Nami Op.gg
Sallisaw Bin Store
Advance Auto.parts Near Me
Swoop Amazon S3
Go Nutrients Intestinal Edge Reviews
Devotion Showtimes Near Showplace Icon At Valley Fair
Theatervoorstellingen in Nieuwegein, het complete aanbod.
Makes A Successful Catch Maybe Crossword Clue
Verilife Williamsport Reviews
Ics 400 Test Answers 2022
Osrs Vorkath Combat Achievements
Ingersoll Greenwood Funeral Home Obituaries
Adams County 911 Live Incident
Gameplay Clarkston
La Fitness Oxford Valley Class Schedule
Latest Posts
Article information

Author: Francesca Jacobs Ret

Last Updated:

Views: 6686

Rating: 4.8 / 5 (48 voted)

Reviews: 95% of readers found this page helpful

Author information

Name: Francesca Jacobs Ret

Birthday: 1996-12-09

Address: Apt. 141 1406 Mitch Summit, New Teganshire, UT 82655-0699

Phone: +2296092334654

Job: Technology Architect

Hobby: Snowboarding, Scouting, Foreign language learning, Dowsing, Baton twirling, Sculpting, Cabaret

Introduction: My name is Francesca Jacobs Ret, I am a innocent, super, beautiful, charming, lucky, gentle, clever person who loves writing and wants to share my knowledge and understanding with you.