or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# PLYFile

1

2

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.

3

4

## Package Information

5

6

- **Package Name**: plyfile

7

- **Language**: Python

8

- **Installation**: `pip install plyfile`

9

- **Dependencies**: NumPy (>=1.21)

10

11

## Core Imports

12

13

```python

14

import plyfile

15

from plyfile import PlyData, PlyElement, PlyProperty, PlyListProperty

16

```

17

18

For exception handling:

19

20

```python

21

from plyfile import PlyParseError, PlyElementParseError, PlyHeaderParseError

22

```

23

24

## Basic Usage

25

26

### Reading PLY Files

27

28

```python

29

from plyfile import PlyData

30

31

# Read PLY file from disk

32

ply_data = PlyData.read('mesh.ply')

33

34

# Access elements by name

35

vertex_element = ply_data['vertex']

36

face_element = ply_data['face']

37

38

# Access element data as NumPy arrays

39

vertices = vertex_element.data

40

faces = face_element.data

41

42

# Print file information

43

print(f"Number of vertices: {len(vertex_element)}")

44

print(f"Number of faces: {len(face_element)}")

45

print(f"Vertex properties: {[prop.name for prop in vertex_element.properties]}")

46

```

47

48

### Writing PLY Files

49

50

```python

51

import numpy as np

52

from plyfile import PlyData, PlyElement

53

54

# Create vertex data

55

vertex_data = np.array([

56

(0.0, 0.0, 0.0, 255, 0, 0),

57

(1.0, 0.0, 0.0, 0, 255, 0),

58

(0.0, 1.0, 0.0, 0, 0, 255)

59

], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'),

60

('red', 'u1'), ('green', 'u1'), ('blue', 'u1')])

61

62

# Create face data with connectivity lists

63

face_data = np.array([

64

([0, 1, 2],),

65

], dtype=[('vertex_indices', 'O')])

66

67

# Create PLY elements

68

vertex_element = PlyElement.describe(vertex_data, 'vertex')

69

face_element = PlyElement.describe(face_data, 'face')

70

71

# Create PLY data and write to file

72

ply_data = PlyData([vertex_element, face_element])

73

ply_data.write('output.ply')

74

```

75

76

## Capabilities

77

78

### PLY Data Container

79

80

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

81

82

```python { .api }

83

class PlyData:

84

def __init__(self, elements=[], text=False, byte_order='=', comments=[], obj_info=[]):

85

"""

86

Initialize PLY data container.

87

88

Parameters:

89

- elements (list): List of PlyElement instances

90

- text (bool): Whether file format is text/ASCII (True) or binary (False)

91

- byte_order (str): Byte order for binary files ('<', '>', '=')

92

- comments (list): Comment lines for header

93

- obj_info (list): Object info lines for header

94

"""

95

96

@staticmethod

97

def read(stream, mmap='c', known_list_len={}):

98

"""

99

Read PLY data from file or stream.

100

101

Parameters:

102

- stream (str or file): Filename or open file object

103

- mmap (str or bool): Memory mapping mode ('c', 'r', 'r+', or False)

104

- known_list_len (dict): Fixed lengths for list properties to enable memory mapping

105

106

Returns:

107

- PlyData: Parsed PLY data

108

109

Raises:

110

- PlyParseError: If file cannot be parsed

111

- ValueError: If stream mode incompatible with PLY format

112

"""

113

114

def write(self, stream):

115

"""

116

Write PLY data to file or stream.

117

118

Parameters:

119

- stream (str or file): Filename or open file object

120

121

Raises:

122

- ValueError: If stream mode incompatible with PLY format

123

"""

124

125

def __getitem__(self, name):

126

"""

127

Get element by name.

128

129

Parameters:

130

- name (str): Element name

131

132

Returns:

133

- PlyElement: The requested element

134

135

Raises:

136

- KeyError: If element not found

137

"""

138

139

def __contains__(self, name):

140

"""

141

Check if element exists.

142

143

Parameters:

144

- name (str): Element name

145

146

Returns:

147

- bool: True if element exists

148

"""

149

150

def __len__(self):

151

"""

152

Get number of elements.

153

154

Returns:

155

- int: Number of elements

156

"""

157

158

def __iter__(self):

159

"""

160

Iterate over elements.

161

162

Yields:

163

- PlyElement: Each element in order

164

"""

165

166

# Properties

167

elements: list # List of PlyElement instances

168

comments: list # Header comment lines

169

obj_info: list # Header object info lines

170

text: bool # Text format flag

171

byte_order: str # Byte order specification

172

header: str # Complete PLY header string

173

```

174

175

### PLY Element Container

176

177

Container for element data with properties and metadata.

178

179

```python { .api }

180

class PlyElement:

181

def __init__(self, name, properties, count, comments=[]):

182

"""

183

Initialize PLY element (internal use - prefer PlyElement.describe).

184

185

Parameters:

186

- name (str): Element name

187

- properties (list): List of PlyProperty instances

188

- count (int): Number of data rows

189

- comments (list): Element comments

190

"""

191

192

@staticmethod

193

def describe(data, name, len_types={}, val_types={}, comments=[]):

194

"""

195

Create PlyElement from NumPy array.

196

197

Parameters:

198

- data (numpy.ndarray): Structured NumPy array with element data

199

- name (str): Element name

200

- len_types (dict): Type specifications for list length fields

201

- val_types (dict): Type specifications for list value fields

202

- comments (list): Element comments

203

204

Returns:

205

- PlyElement: New element instance

206

207

Raises:

208

- TypeError: If data is not NumPy array

209

- ValueError: If array format unsupported

210

"""

211

212

def ply_property(self, name):

213

"""

214

Get property by name.

215

216

Parameters:

217

- name (str): Property name

218

219

Returns:

220

- PlyProperty: The requested property

221

222

Raises:

223

- KeyError: If property not found

224

"""

225

226

def dtype(self, byte_order='='):

227

"""

228

Get NumPy dtype for element data.

229

230

Parameters:

231

- byte_order (str): Byte order specification

232

233

Returns:

234

- numpy.dtype: Data type description

235

"""

236

237

def __getitem__(self, key):

238

"""

239

Access element data array.

240

241

Parameters:

242

- key: Array index or slice

243

244

Returns:

245

- Data from underlying NumPy array

246

"""

247

248

def __setitem__(self, key, value):

249

"""

250

Modify element data array.

251

252

Parameters:

253

- key: Array index or slice

254

- value: New value

255

"""

256

257

def __len__(self):

258

"""

259

Get number of data rows.

260

261

Returns:

262

- int: Number of rows

263

"""

264

265

def __contains__(self, name):

266

"""

267

Check if property exists.

268

269

Parameters:

270

- name (str): Property name

271

272

Returns:

273

- bool: True if property exists

274

"""

275

276

# Properties

277

name: str # Element name

278

count: int # Number of data rows

279

data: numpy.ndarray # Structured array with element data

280

properties: list # List of PlyProperty instances

281

comments: list # Element comments

282

header: str # PLY header block for this element

283

```

284

285

### Property Definitions

286

287

Property metadata describing scalar and list data fields.

288

289

```python { .api }

290

class PlyProperty:

291

def __init__(self, name, val_dtype):

292

"""

293

Initialize scalar property.

294

295

Parameters:

296

- name (str): Property name

297

- val_dtype (str): PLY or NumPy data type specification

298

"""

299

300

def dtype(self, byte_order='='):

301

"""

302

Get NumPy dtype string.

303

304

Parameters:

305

- byte_order (str): Byte order specification

306

307

Returns:

308

- str: NumPy dtype string

309

"""

310

311

# Properties

312

name: str # Property name

313

val_dtype: str # NumPy data type code

314

315

class PlyListProperty(PlyProperty):

316

def __init__(self, name, len_dtype, val_dtype):

317

"""

318

Initialize list property.

319

320

Parameters:

321

- name (str): Property name

322

- len_dtype (str): Data type for list length field

323

- val_dtype (str): Data type for list elements

324

"""

325

326

def list_dtype(self, byte_order='='):

327

"""

328

Get NumPy dtypes for list components.

329

330

Parameters:

331

- byte_order (str): Byte order specification

332

333

Returns:

334

- tuple: (length_dtype, value_dtype)

335

"""

336

337

def dtype(self, byte_order='='):

338

"""

339

Get NumPy dtype for property field (always object type).

340

341

Parameters:

342

- byte_order (str): Byte order specification

343

344

Returns:

345

- str: Always '|O' for object arrays

346

"""

347

348

# Properties (inherited from PlyProperty)

349

name: str # Property name

350

val_dtype: str # NumPy data type for list elements

351

len_dtype: str # NumPy data type for list length

352

```

353

354

### Exception Handling

355

356

Error handling for PLY file parsing and validation.

357

358

```python { .api }

359

class PlyParseError(Exception):

360

"""Base class for PLY parsing errors."""

361

362

class PlyElementParseError(PlyParseError):

363

def __init__(self, message, element=None, row=None, prop=None):

364

"""

365

Element parsing error.

366

367

Parameters:

368

- message (str): Error description

369

- element (PlyElement): Element being parsed

370

- row (int): Row number where error occurred

371

- prop (PlyProperty): Property being parsed

372

"""

373

374

# Properties

375

message: str # Error message

376

element: PlyElement # Element context

377

row: int # Row number

378

prop: PlyProperty # Property context

379

380

class PlyHeaderParseError(PlyParseError):

381

def __init__(self, message, line=None):

382

"""

383

Header parsing error.

384

385

Parameters:

386

- message (str): Error description

387

- line (str): Header line where error occurred

388

"""

389

390

# Properties

391

message: str # Error message

392

line: str # Header line context

393

```

394

395

## Advanced Usage Examples

396

397

### Memory Mapping for Large Files

398

399

```python

400

from plyfile import PlyData

401

402

# Enable memory mapping for better performance with large files

403

# Requires known list lengths for elements with list properties

404

known_lengths = {

405

'vertex': {}, # No list properties

406

'face': {'vertex_indices': 3} # Triangular faces

407

}

408

409

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

410

```

411

412

### Custom Data Types

413

414

```python

415

import numpy as np

416

from plyfile import PlyElement

417

418

# Create data with custom list length and value types

419

vertex_data = np.array([

420

(0.0, 0.0, 0.0, [255, 128, 64]),

421

(1.0, 0.0, 0.0, [0, 255, 128]),

422

], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('rgb', 'O')])

423

424

# Specify types for list properties

425

element = PlyElement.describe(

426

vertex_data,

427

'vertex',

428

len_types={'rgb': 'u1'}, # 8-bit unsigned for list length

429

val_types={'rgb': 'u1'} # 8-bit unsigned for RGB values

430

)

431

```

432

433

### File Format Control

434

435

```python

436

from plyfile import PlyData, PlyElement

437

438

# Create data

439

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

440

441

# Write as ASCII text format

442

ply_ascii = PlyData([element], text=True)

443

ply_ascii.write('mesh_ascii.ply')

444

445

# Write as binary format with specific byte order

446

ply_binary = PlyData([element], text=False, byte_order='<') # Little-endian

447

ply_binary.write('mesh_binary.ply')

448

```

449

450

### Comments and Metadata

451

452

```python

453

from plyfile import PlyData, PlyElement

454

455

# Add comments and object info to PLY file

456

element = PlyElement.describe(data, 'vertex', comments=['Vertex data'])

457

458

ply_data = PlyData(

459

[element],

460

comments=['Generated by my application', 'Processed on 2024-01-01'],

461

obj_info=['Author: John Doe', 'Version: 1.0']

462

)

463

ply_data.write('annotated_mesh.ply')

464

```