or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-plyfile

NumPy-based PLY format input and output for Python with comprehensive support for reading and writing PLY polygon mesh files

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/plyfile@1.1.x

To install, run

npx @tessl/cli install tessl/pypi-plyfile@1.1.0

index.mddocs/

PLYFile

NumPy-based PLY format input and output for Python. This library provides comprehensive support for reading and writing PLY (Polygon File Format) files, which are commonly used for storing 3D polygon mesh data in computer graphics and scientific computing applications.

Package Information

  • Package Name: plyfile
  • Language: Python
  • Installation: pip install plyfile
  • Dependencies: NumPy (>=1.21)

Core Imports

import plyfile
from plyfile import PlyData, PlyElement, PlyProperty, PlyListProperty

For exception handling:

from plyfile import PlyParseError, PlyElementParseError, PlyHeaderParseError

Basic Usage

Reading PLY Files

from plyfile import PlyData

# Read PLY file from disk
ply_data = PlyData.read('mesh.ply')

# Access elements by name
vertex_element = ply_data['vertex']
face_element = ply_data['face']

# Access element data as NumPy arrays
vertices = vertex_element.data
faces = face_element.data

# Print file information
print(f"Number of vertices: {len(vertex_element)}")
print(f"Number of faces: {len(face_element)}")
print(f"Vertex properties: {[prop.name for prop in vertex_element.properties]}")

Writing PLY Files

import numpy as np
from plyfile import PlyData, PlyElement

# Create vertex data
vertex_data = np.array([
    (0.0, 0.0, 0.0, 255, 0, 0),
    (1.0, 0.0, 0.0, 0, 255, 0),
    (0.0, 1.0, 0.0, 0, 0, 255)
], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), 
          ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')])

# Create face data with connectivity lists
face_data = np.array([
    ([0, 1, 2],),
], dtype=[('vertex_indices', 'O')])

# Create PLY elements
vertex_element = PlyElement.describe(vertex_data, 'vertex')
face_element = PlyElement.describe(face_data, 'face')

# Create PLY data and write to file
ply_data = PlyData([vertex_element, face_element])
ply_data.write('output.ply')

Capabilities

PLY Data Container

The main container for PLY file data, including elements, comments, and format information.

class PlyData:
    def __init__(self, elements=[], text=False, byte_order='=', comments=[], obj_info=[]):
        """
        Initialize PLY data container.
        
        Parameters:
        - elements (list): List of PlyElement instances
        - text (bool): Whether file format is text/ASCII (True) or binary (False)
        - byte_order (str): Byte order for binary files ('<', '>', '=')
        - comments (list): Comment lines for header
        - obj_info (list): Object info lines for header
        """
    
    @staticmethod
    def read(stream, mmap='c', known_list_len={}):
        """
        Read PLY data from file or stream.
        
        Parameters:
        - stream (str or file): Filename or open file object
        - mmap (str or bool): Memory mapping mode ('c', 'r', 'r+', or False)
        - known_list_len (dict): Fixed lengths for list properties to enable memory mapping
        
        Returns:
        - PlyData: Parsed PLY data
        
        Raises:
        - PlyParseError: If file cannot be parsed
        - ValueError: If stream mode incompatible with PLY format
        """
    
    def write(self, stream):
        """
        Write PLY data to file or stream.
        
        Parameters:
        - stream (str or file): Filename or open file object
        
        Raises:
        - ValueError: If stream mode incompatible with PLY format
        """
    
    def __getitem__(self, name):
        """
        Get element by name.
        
        Parameters:
        - name (str): Element name
        
        Returns:
        - PlyElement: The requested element
        
        Raises:
        - KeyError: If element not found
        """
    
    def __contains__(self, name):
        """
        Check if element exists.
        
        Parameters:
        - name (str): Element name
        
        Returns:
        - bool: True if element exists
        """
    
    def __len__(self):
        """
        Get number of elements.
        
        Returns:
        - int: Number of elements
        """
    
    def __iter__(self):
        """
        Iterate over elements.
        
        Yields:
        - PlyElement: Each element in order
        """

# Properties
elements: list  # List of PlyElement instances
comments: list  # Header comment lines
obj_info: list  # Header object info lines
text: bool      # Text format flag
byte_order: str # Byte order specification
header: str     # Complete PLY header string

PLY Element Container

Container for element data with properties and metadata.

class PlyElement:
    def __init__(self, name, properties, count, comments=[]):
        """
        Initialize PLY element (internal use - prefer PlyElement.describe).
        
        Parameters:
        - name (str): Element name
        - properties (list): List of PlyProperty instances
        - count (int): Number of data rows
        - comments (list): Element comments
        """
    
    @staticmethod
    def describe(data, name, len_types={}, val_types={}, comments=[]):
        """
        Create PlyElement from NumPy array.
        
        Parameters:
        - data (numpy.ndarray): Structured NumPy array with element data
        - name (str): Element name
        - len_types (dict): Type specifications for list length fields
        - val_types (dict): Type specifications for list value fields
        - comments (list): Element comments
        
        Returns:
        - PlyElement: New element instance
        
        Raises:
        - TypeError: If data is not NumPy array
        - ValueError: If array format unsupported
        """
    
    def ply_property(self, name):
        """
        Get property by name.
        
        Parameters:
        - name (str): Property name
        
        Returns:
        - PlyProperty: The requested property
        
        Raises:
        - KeyError: If property not found
        """
    
    def dtype(self, byte_order='='):
        """
        Get NumPy dtype for element data.
        
        Parameters:
        - byte_order (str): Byte order specification
        
        Returns:
        - numpy.dtype: Data type description
        """
    
    def __getitem__(self, key):
        """
        Access element data array.
        
        Parameters:
        - key: Array index or slice
        
        Returns:
        - Data from underlying NumPy array
        """
    
    def __setitem__(self, key, value):
        """
        Modify element data array.
        
        Parameters:
        - key: Array index or slice
        - value: New value
        """
    
    def __len__(self):
        """
        Get number of data rows.
        
        Returns:
        - int: Number of rows
        """
    
    def __contains__(self, name):
        """
        Check if property exists.
        
        Parameters:
        - name (str): Property name
        
        Returns:
        - bool: True if property exists
        """

# Properties
name: str               # Element name
count: int              # Number of data rows
data: numpy.ndarray     # Structured array with element data
properties: list        # List of PlyProperty instances
comments: list          # Element comments
header: str             # PLY header block for this element

Property Definitions

Property metadata describing scalar and list data fields.

class PlyProperty:
    def __init__(self, name, val_dtype):
        """
        Initialize scalar property.
        
        Parameters:
        - name (str): Property name
        - val_dtype (str): PLY or NumPy data type specification
        """
    
    def dtype(self, byte_order='='):
        """
        Get NumPy dtype string.
        
        Parameters:
        - byte_order (str): Byte order specification
        
        Returns:
        - str: NumPy dtype string
        """

# Properties
name: str       # Property name
val_dtype: str  # NumPy data type code

class PlyListProperty(PlyProperty):
    def __init__(self, name, len_dtype, val_dtype):
        """
        Initialize list property.
        
        Parameters:
        - name (str): Property name
        - len_dtype (str): Data type for list length field
        - val_dtype (str): Data type for list elements
        """
    
    def list_dtype(self, byte_order='='):
        """
        Get NumPy dtypes for list components.
        
        Parameters:
        - byte_order (str): Byte order specification
        
        Returns:
        - tuple: (length_dtype, value_dtype)
        """
    
    def dtype(self, byte_order='='):
        """
        Get NumPy dtype for property field (always object type).
        
        Parameters:
        - byte_order (str): Byte order specification
        
        Returns:
        - str: Always '|O' for object arrays
        """

# Properties (inherited from PlyProperty)
name: str        # Property name
val_dtype: str   # NumPy data type for list elements
len_dtype: str   # NumPy data type for list length

Exception Handling

Error handling for PLY file parsing and validation.

class PlyParseError(Exception):
    """Base class for PLY parsing errors."""

class PlyElementParseError(PlyParseError):
    def __init__(self, message, element=None, row=None, prop=None):
        """
        Element parsing error.
        
        Parameters:
        - message (str): Error description
        - element (PlyElement): Element being parsed
        - row (int): Row number where error occurred
        - prop (PlyProperty): Property being parsed
        """

# Properties
message: str        # Error message
element: PlyElement # Element context
row: int           # Row number
prop: PlyProperty  # Property context

class PlyHeaderParseError(PlyParseError):
    def __init__(self, message, line=None):
        """
        Header parsing error.
        
        Parameters:
        - message (str): Error description
        - line (str): Header line where error occurred
        """

# Properties
message: str # Error message
line: str    # Header line context

Advanced Usage Examples

Memory Mapping for Large Files

from plyfile import PlyData

# Enable memory mapping for better performance with large files
# Requires known list lengths for elements with list properties
known_lengths = {
    'vertex': {},  # No list properties
    'face': {'vertex_indices': 3}  # Triangular faces
}

ply_data = PlyData.read('large_mesh.ply', mmap='c', known_list_len=known_lengths)

Custom Data Types

import numpy as np
from plyfile import PlyElement

# Create data with custom list length and value types
vertex_data = np.array([
    (0.0, 0.0, 0.0, [255, 128, 64]),
    (1.0, 0.0, 0.0, [0, 255, 128]),
], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('rgb', 'O')])

# Specify types for list properties
element = PlyElement.describe(
    vertex_data, 
    'vertex',
    len_types={'rgb': 'u1'},  # 8-bit unsigned for list length
    val_types={'rgb': 'u1'}   # 8-bit unsigned for RGB values
)

File Format Control

from plyfile import PlyData, PlyElement

# Create data
element = PlyElement.describe(data, 'vertex')

# Write as ASCII text format
ply_ascii = PlyData([element], text=True)
ply_ascii.write('mesh_ascii.ply')

# Write as binary format with specific byte order
ply_binary = PlyData([element], text=False, byte_order='<')  # Little-endian
ply_binary.write('mesh_binary.ply')

Comments and Metadata

from plyfile import PlyData, PlyElement

# Add comments and object info to PLY file
element = PlyElement.describe(data, 'vertex', comments=['Vertex data'])

ply_data = PlyData(
    [element],
    comments=['Generated by my application', 'Processed on 2024-01-01'],
    obj_info=['Author: John Doe', 'Version: 1.0']
)
ply_data.write('annotated_mesh.ply')