.. _shapeprop : Shape Properties ================ Shape properties are measurements of the shape of a protein when it is viewed from a specific orientation. Examples include the projected area, perimeter, bounding-box size, and shape moments. Before a shape property can be calculated, the corresponding shape must already have been calculated by a ``ShapeCalculator``, as described in :ref:`shapes`. Using Shape Properties ---------------------- Before calculating a shape property, we first need to load a protein and calculate a shape for it. Here, we use the ``8JXW`` structure, as described in :ref:`loading_protein`, and calculate an alpha shape for each sampled orientation. See :ref:`shapes` for more details on shape calculation. .. code-block:: python :caption: Load Protein and Calculate Alpha Shape import ProteoTwirl.ProteinRotation as pt protein_structure = pt.ProteinRotation( protein = "Test_Data/8JXW_H.pdb", selection = "protein and segid E and not element H", base_rotation = "principle", center_selection = True, ) protein_structure.add_property( property = "Alphashape", alpha = 0.5, hole_fill = 0.1, rotation_res = 64, use_default = False, ) # Added Alpha_Shape_50_HF10 To calculate a shape property, specify the name of the previously calculated shape using ``shape_prop_name``. The rotation settings should match those used for the shape calculation, including ``rotation_res``, ``rotation_range``, and related options, so that each property value corresponds to the same sampled orientation. .. code-block:: python :caption: Calculate Shape Area protein_structure.add_property( property = "shape.area", shape_prop_name = "Alpha_Shape_50_HF10", rotation_res = 64, use_default = False, ) # Added Alpha_Shape_50_HF10_area The first shape added to a ``ProteinRotation`` object is set as the default shape. If a shape property should be calculated for this default shape, ``shape_prop_name`` does not need to be specified. See :ref:`defshape` for more information on default shapes. Available Shape Properties -------------------------- ProteoTwirl includes several built-in shape properties. These are listed below. .. list-table:: Shape Properties :header-rows: 1 :widths: 30 30 30 60 :class: centered-table * - Property - Name - Return Type - Description * - Area - ``shape.area`` - ``float`` - Calculates the area of the shape. * - Perimeter - ``shape.perimeter`` - ``float`` - Calculates the perimeter length of the shape. * - Bounding X Length - ``shape.bounds_xspan`` - ``float`` - Calculates the x-axis span of the smallest bounding box containing the shape. * - Bounding Y Length - ``shape.bounds_yspan`` - ``float`` - Calculates the y-axis span of the smallest bounding box containing the shape. * - Number of Components - ``shape.component_count`` - ``int`` - Counts how many disconnected polygons the shape consists of. * - First `Hu moment `_ - ``shape.hu1`` - ``float`` - Calculates the first Hu moment of the shape. * - Second `Hu moment `_ - ``shape.hu2`` - ``float`` - Calculates the second Hu moment of the shape. * - Third `Hu moment `_ - ``shape.hu3`` - ``float`` - Calculates the third Hu moment of the shape. * - Fourth `Hu moment `_ - ``shape.hu4`` - ``float`` - Calculates the fourth Hu moment of the shape. * - Fifth `Hu moment `_ - ``shape.hu5`` - ``float`` - Calculates the fifth Hu moment of the shape. * - Sixth `Hu moment `_ - ``shape.hu6`` - ``float`` - Calculates the sixth Hu moment of the shape. * - Seventh `Hu moment `_ - ``shape.hu7`` - ``float`` - Calculates the seventh Hu moment of the shape. * - All `Hu moments `_ - ``shape.hu_moments`` - ``list[float]`` - Calculates all seven Hu moments of the shape. Custom Shape Property --------------------- You can define a custom shape property in ProteoTwirl by defining a function that takes a Shapely geometry object as input and returns a value. Here, we implement a simple circularity measure: .. math:: :class: center \text{circularity} = \frac{4\pi \cdot \text{Area}}{\text{Perimeter}^2} A perfect circle has a circularity of ``1``. Less circular shapes have lower values. .. code-block:: python :caption: Define a Circularity Function import numpy as np from shapely.geometry import MultiPolygon def circularity(shape, **kwargs): polygon = shape # If the shape contains multiple disconnected polygons, # calculate circularity for the largest component. if isinstance(shape, MultiPolygon): polygon = max(shape.geoms, key=lambda geom: geom.area) # Avoid division by zero for empty or degenerate shapes. if polygon.is_empty or polygon.length == 0: return np.nan return (4 * np.pi * polygon.area) / (polygon.length ** 2) The easiest way to use this function as a shape property is to register it as a shape feature. .. code-block:: python :caption: Register the Circularity Shape Property from ProteoTwirl.Properties.ShapeProperty import _register_shape_feature _register_shape_feature("circularity", circularity) The new property can then be calculated like any other shape property. .. code-block:: python :caption: Calculate the Circularity Shape Property protein_structure.add_property( property = "shape.circularity", shape_prop_name = "Alpha_Shape_50_HF10", rotation_res = 64, use_default = False, ) # Added Alpha_Shape_50_HF10_circularity Finally, visualize the new property. .. code-block:: python :caption: Plot the Circularity Shape Property protein_structure.plot_property_3d( "Alpha_Shape_50_HF10_circularity", background="#14181e", ) .. raw:: html