Cartographic Plots#

This guide uses the example system loaded in Visualization Example System. Please load the example system before following the rest of the tutorial.

Introduction#

ProteoTwirl calculates angle-dependent properties. This means we have a set of angles indicating where a protein is “viewed” from, and an associated value for each angle.

To plot this, we have to map all angles, which can be seen as points on a sphere, to a flat plane. This is impossible to do without distortion (see Gauss’s Theorema Egregium).

However, many approximate methods with different trade-offs have been developed in cartography to create maps of the Earth. We can reuse these cartographic projections to plot our angle-dependent properties. In practice, ProteoTwirl uses CartoPy to create projections. A list of projections available in CartoPy can be found here.

Quick Plots#

The easiest way to create a cartographic plot for a given property is to use the plot_property function. This function will create a contour plot of the property requested, with interpolation between the data points. The function also creates a scatter plot on top with the original data points, with point size indicating value.

Property Plot#
import cartopy.crs as ccrs

fig, ax = protein_structure.plot_property(
        property        ="mean_Hydropathy",         # name of property
        cmap            ="RdPu",                    # matplotlib colormap
        projection      = ccrs.Stereographic(),     # projection
        scatter_size    =(1,150),                   # size of scatter plot
        interp_degre    = 16,                       # how many points to interpolate
        scatter_col     = "#222222",               # scatter-plot point color
        levels          = 16                        # number of contour levels
    )
../../_images/8JXW_Hydropathy.png

A quick plot showing how a shape looks at different angles can also be made using plot_shape as shown below.

Shape Plot#
fig, ax = protein_structure.plot_shape(
    shape_property  = "Alpha_Shape_45_HF20",
    projection      = ccrs.EckertIII(),
    shape_color     = "#ffaaaa",
    shape_size      = 50,
    figsize         = (13,8)
)

# Setting a background color, so plot is visible on dark and light mode
# of documentation
ax.patch.set_facecolor("#14181e")
../../_images/8JXW_Alpha_Shape.png

Contour Plots#

Cartographic contour plots can be made using the plot_carto_contour function. You must provide arrays of \(\phi\) and \(\theta\) angles, together with an array of values.

Here, we will get the angles and values via the get_property function, as shown below.

Get Property & Angles#
value,angles = protein_structure.get_property(
    property_name   = "mean_Hydropathy",
    return_angle    = True
    )["mean_Hydropathy"]

# value is a list of items, in this case floating-point values
print(len(value))

>>> 64

# angles is a numpy array of phi and theta pairs.
print(angles.shape)

>>> (64, 2)

These can then be plotted using the plot_carto_contour function, as shown below.

Plotting using plot_carto_contour#
from ProteoTwirl.Visualization.CatographyPlot import plot_carto_contour

ax = plot_carto_contour(
    angles          = angles,           # angle
    values          = value,            # values/height
    projection      = ccrs.EckertI(),   # projection to use
    cmap            = "plasma",         # matplotlib colormap
    figsize         = (13,13),          # figure size

    # gridline can be true/false or a dict with gridline keyword-arguments
    gridlines       = {
        "colors"        : "#ffffff"
    },

    # contour_labels can be true/false or a dict with contour label keyword-arguments
    contour_labels  = {
        "colors"        : "#ffffff",
        "fmt"           : "{:.2f} ".format,
        },

    # contour_lines can be true/false or a dict with contour line keyword-arguments
    contour_lines={
        "colors"        : "#dddddd",
        "linewidths"    : 0.6,
        "linestyles"    :"dashed"
    }
)
../../_images/8JXW_Hydropathy_contour.png

It is also possible to use categorical values when creating contour plots.

Plotting using plot_carto_contour#
from ProteoTwirl.Visualization.CatographyPlot import plot_carto_contour

value,angles = protein_structure.get_property(
    property_name   = "mean_Hydropathy",
    return_angle    = True
    )["mean_Hydropathy"]

# Convert to categorical
categorical_values = ["High" if v > 0.7 else "Medium" if v > 0.6 else "Low" for v in value]


ax = plot_carto_contour(
    angles          = angles,
    values          = categorical_values,
    projection      = ccrs.EckertI(),
    categorical     = True,
    figsize         = (13,6),
    category_colors = {"High": "#FFaaaa", "Medium": "#aaFFaa", "Low": "#aaaaFF"}

)
../../_images/8JXW_Hydropathy_contour_categorical.png

Scatter Plots#

You can alternatively make a scatter plot of the different angles for a given property using plot_carto_scatter. plot_carto_scatter also allows scaling and coloring of the scatter points according to a value, such as the "mean_Hydropathy" also used for contour plots.

Plotting using plot_carto_scatter#
from ProteoTwirl.Visualization.CatographyPlot import plot_carto_scatter

ax = plot_carto_scatter(
    angles          = angles,           # angle

    # If string, will color all by same color, but if list of values
    # will color according to the colormap in cmap
    color           = value,

    # If single value will use that for all, if array of value will scale
    # all sizes to the range of sizes in smin_max_plot, according to their value
    size            = value,

    projection      = ccrs.EckertIII(),   # projection to use
    cmap            = "viridis",         # matplotlib colormap
    figsize         = (13,6),          # figure size

    smin_max_plot   = (10,1500),          # set min and max marker size

    # gridline can be true/false or a dict with gridline keyword-arguments
    gridlines       = {
        "colors"        : "#ffffff",
        "linewidth"     : 1.5,
    },


)

# Setting a background color, so plot is visible on dark and light mode
# of documentation
ax.patch.set_facecolor("#14181e")
../../_images/8JXW_Hydropathy_scatter.png

Shape-Scatter Plots#

The cartographic scatter plot also allows you to use custom shapes as the marker style on the plot. This, for example, allows us to make a plot showing how the protein looks at different angles.

We can combine this with the hydropathy values from before since they are present in the same angle space (matching the same set of angles). We confirm this by using:

Checking angle-space#
hydropathy_angle_space  = protein_structure.get_angle_space_of_property("mean_Hydropathy")
alpha_shape_angle_space = protein_structure.get_angle_space_of_property("Alpha_Shape_45_HF20")

print(hydropathy_angle_space == alpha_shape_angle_space)

>>> True

We can then plot the shape of the protein, and color it according to the mean hydropathy index of exposed residues from that angle.

Plotting Shapes by Angle#
shape,angles = protein_structure.get_property(
    property_name   = "Alpha_Shape_45_HF20",
    return_angle    = True
    )["Alpha_Shape_45_HF20"]

value,_ = protein_structure.get_property(
    property_name   = "mean_Hydropathy",
    return_angle    = True
    )["mean_Hydropathy"]

ax = plot_carto_scatter(
    angles          = angles,           # angle
    color           = value,
    size            = 50,
    marker          = shape,

    projection      = ccrs.EckertIII(),   # projection to use
    cmap            = "viridis",         # matplotlib colormap
    figsize         = (13,7),          # figure size

    # gridline can be true/false or a dict with gridline keyword-arguments
    gridlines       = {
        "colors"        : "#ffffff",
        "linewidth"     : 1.5,
    },


)
../../_images/8JXW_Hydropathy_scatter_shape.png

When plotting shapes, there are two additional options to keep in mind for how the shapes are rendered. The first of these is shape_size, which determines the resolution at which the shapes are rendered. Below is an example of low-resolution rendering (using shape_size = 8 and size = 40, but otherwise the same settings as above).

../../_images/8JXW_Hydropathy_scatter_shape_low_res.png

The other is scale_shape. If True, this will scale the shapes to their correct relative sizes, allowing better comparison of the size of the protein at different angles. On the other hand, this can make some angles hard to see if they are small, and it precludes scaling the shapes according to some value.

Below is an example of a very elongated protein (5BU5) where scale_shape is either turned on or off, highlighting that when it is turned on it can be hard to see some smaller shapes.

The top plot uses scale_shape = False, and the bottom plot uses scale_shape = True.

../../_images/5BU5_scale_False.png
../../_images/5BU5_scale_True.png

Note on Central Longitude#

Note that if you change the central_longitude in a projection, then you need to specify that value as central_longitude in the function you are using (plot_property, plot_shape, plot_carto_contour, or plot_carto_scatter).