0

I have the following Python code that generates the attached image. I expect that by specifying the line thickness, the line would span the range from [-0.5, 0.5], but it exceeds it. Any ideas why?

Thanks in advance.

import plotly.graph_objects as go

def width_to_xcoord (WidthOffsetFromXCenter, XCenter, 
                     XMin, XMax, 
                     WidthMin, WidthMax):
    """
    Convert the width of the line to the X-coordinate within the specified range.
    WidthOffsetFromXCenter - The width to convert to the X-coordinates.  This 
                is in Width Units that is offset from "XCenter"
    XCenter - The X-location in X-units to center the plot.
    XMin - The X-location in X-units that corresponds to the WidthMin location
              that is in width units. 
    XMax - The X-location in X-units that corresponds to the WidthMax location
              that is in width units. 
    WidthMin - The width location in width units that corresponds to the 
              XMin location that is in X-units units. 
    WidthMax - The width location in width units that corresponds to the 
              XMax location that is in X-units units. 
                      
    """
    #  Linear Transform between the X-units to the Width Units.  This is needed
    #    to find the offset to put "Width".
    SlopeXtoW = (WidthMax - WidthMin) / (XMax - XMin)
    InterceptXtoW = WidthMax - (SlopeXtoW * XMax)
    WidthCenter = SlopeXtoW * XCenter + InterceptXtoW
    
    #  Linear Transform from the width units to the X-units. 
    Slope = 1.0 / SlopeXtoW 
    Intercept = XMax - (Slope * WidthMax)
    WidthOffset = WidthOffsetFromXCenter + WidthCenter
    XCoordinate = (Slope * WidthOffset) + Intercept
    XOffset     = XCenter + XCoordinate
    return XOffset


def create_well_construction_plot (casing_intervals):
    
    #  Constants 
    LineWidth         = 400
    PixelWidthOfPlot  = 800
    PixelHeightOfPlot = 600
    MinX = -1
    MaxX = 1
    XCenter = 0
    LineScalar   = 1
    
    #  Plot parameters
    left_px   = 50
    right_px  = 50
    top_py    = 50
    bottom_py = 50
    W_px = PixelWidthOfPlot + left_px + right_px
    H_px = PixelHeightOfPlot + top_py + bottom_py

    fig_layout = go.Layout(
        width = W_px,
        height = H_px,
        margin = dict(
            l = left_px,
            r = right_px,
            t = top_py,
            b = bottom_py
            )
        # ),
        # annotations = annot_list
    )

    fig = go.Figure(layout=fig_layout)
    # fig = go.Figure()

    # Reverse the y-axis
    fig.update_layout(
        yaxis=dict(autorange='reversed'),
    )
    
    # Plot casing intervals
    for i, interval in enumerate(casing_intervals):
        # Set line thickness 
       
        print (" LineWidth = " + (str (LineWidth)) )
        
        # Plot (outer) casing interval line
        fig.add_shape(
            type='line',
            x0=XCenter, y0=casing_intervals [i],
            x1=XCenter, y1=0,
            line=dict(color='blue', width=(LineScalar*LineWidth)),
            layer='below'
        )

        #  Plot a triangle at the end of the casing line. 
        
        XTriangle = width_to_xcoord ((0.5*LineWidth), 
                                     XCenter, MinX, MaxX, 
                                     0, PixelWidthOfPlot)
        print (" XTriangle = " + (str (XTriangle)) )

        fig.add_trace(
            go.Scatter(
                x=[XTriangle], y=[casing_intervals [i]], # Coordinates of the triangle vertex
                mode='markers',
                marker=dict(symbol='triangle-up', size=10, color='red'), 
                showlegend=False
            )
        )

    # Test Marker #2
    XTriangle = width_to_xcoord ((0.25*PixelWidthOfPlot), 
                                           XCenter, MinX, MaxX, 
                                           0, PixelWidthOfPlot)
    print (" XTriangle = " + (str (XTriangle)) )

    fig.add_trace(
        go.Scatter(
            x=[XTriangle], y=[casing_intervals [i]+100], # Coordinates of the triangle vertex
            mode='markers',
            marker=dict(symbol='triangle-up', size=10, color='green'), 
            showlegend=False
        )
    )

    # Set layout properties
    fig.update_layout(
        title='Plot',
        xaxis_title='X',
        yaxis_title='Y',
        showlegend=False
    )

    # Set the X-axis range. 
    fig.update_xaxes(range=[MinX, MaxX])

    # Set y-axis range to match the maximum depth
    max_depth = casing_intervals[-1]
    fig.update_yaxes(range=[0, (max_depth + 100)])
    

    # Show the plot
    fig.show()
    fig.write_image ("TestPlot.png")

# Example data for casing intervals
casing_intervals = [1200]

# Create the well construction plot for casing intervals
create_well_construction_plot (casing_intervals)

enter image description here

Steven Rumbalski
  • 44,786
  • 9
  • 89
  • 119
STBoerner
  • 1
  • 2
  • See StackOverflow help [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). Most people aren't going to want to wade through this much code to answer your question. – Steven Rumbalski Jun 05 '23 at 21:05

1 Answers1

0

Yes, of course.

In the process of minimizing the code, I may have inadvertently solved my own problem. I eliminated the "fig.update_layout" code that defined the title of the plot and of the axes, and the line thickness changed to what I expected it to be. I added it back in and increased the left and right margins (left_px & right_px) to 75, and the line thickness was again as I expected. Apparently, if the margin is not large enough to accommodate the axes, Plotly updates the pixel size of the plot.

Thank you for your help.

STBoerner
  • 1
  • 2