gsply 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gsply/__init__.py +55 -0
- gsply/formats.py +226 -0
- gsply/py.typed +1 -0
- gsply/reader.py +894 -0
- gsply/writer.py +1019 -0
- gsply-0.1.0.dist-info/METADATA +520 -0
- gsply-0.1.0.dist-info/RECORD +11 -0
- gsply-0.1.0.dist-info/WHEEL +5 -0
- gsply-0.1.0.dist-info/licenses/LICENSE +21 -0
- gsply-0.1.0.dist-info/top_level.txt +1 -0
- gsply-0.1.0.dist-info/zip-safe +1 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gsply
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Ultra-fast Gaussian Splatting PLY I/O library - pure Python, zero dependencies
|
|
5
|
+
Author-email: OpsiClear <yehe@opsiclear.com>
|
|
6
|
+
Maintainer-email: OpsiClear <yehe@opsiclear.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/OpsiClear/gsply
|
|
9
|
+
Project-URL: Repository, https://github.com/OpsiClear/gsply
|
|
10
|
+
Project-URL: Issues, https://github.com/OpsiClear/gsply/issues
|
|
11
|
+
Project-URL: Documentation, https://github.com/OpsiClear/gsply#readme
|
|
12
|
+
Keywords: gaussian-splatting,ply,3d,point-cloud,compression,nerf,3dgs
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering
|
|
22
|
+
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Operating System :: OS Independent
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: numpy>=1.20.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
32
|
+
Requires-Dist: build; extra == "dev"
|
|
33
|
+
Requires-Dist: twine; extra == "dev"
|
|
34
|
+
Provides-Extra: benchmark
|
|
35
|
+
Requires-Dist: open3d>=0.17.0; extra == "benchmark"
|
|
36
|
+
Requires-Dist: plyfile>=0.9.0; extra == "benchmark"
|
|
37
|
+
Provides-Extra: jit
|
|
38
|
+
Requires-Dist: numba>=0.59.0; extra == "jit"
|
|
39
|
+
Provides-Extra: all
|
|
40
|
+
Requires-Dist: pytest>=7.0; extra == "all"
|
|
41
|
+
Requires-Dist: pytest-cov; extra == "all"
|
|
42
|
+
Requires-Dist: build; extra == "all"
|
|
43
|
+
Requires-Dist: twine; extra == "all"
|
|
44
|
+
Requires-Dist: open3d>=0.17.0; extra == "all"
|
|
45
|
+
Requires-Dist: plyfile>=0.9.0; extra == "all"
|
|
46
|
+
Requires-Dist: numba>=0.59.0; extra == "all"
|
|
47
|
+
Dynamic: license-file
|
|
48
|
+
|
|
49
|
+
<div align="center">
|
|
50
|
+
|
|
51
|
+
# gsply
|
|
52
|
+
|
|
53
|
+
### Ultra-Fast Gaussian Splatting PLY I/O Library
|
|
54
|
+
|
|
55
|
+
[](https://www.python.org/downloads/)
|
|
56
|
+
[](LICENSE)
|
|
57
|
+
[](https://pypi.org/)
|
|
58
|
+
[](#testing)
|
|
59
|
+
[](https://github.com/astral-sh/ruff)
|
|
60
|
+
|
|
61
|
+
**6.3x faster reads | 1.4x faster writes | Zero dependencies | Pure Python**
|
|
62
|
+
|
|
63
|
+
[Features](#features) | [Installation](#installation) | [Quick Start](#quick-start) | [Performance](#performance) | [Documentation](#documentation)
|
|
64
|
+
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Overview
|
|
70
|
+
|
|
71
|
+
**gsply** is a pure Python library for ultra-fast reading and writing of Gaussian Splatting PLY files. Built specifically for performance-critical applications, gsply achieves 6.3x faster reads and 1.4x faster writes compared to plyfile, with zero external dependencies beyond numpy.
|
|
72
|
+
|
|
73
|
+
**Why gsply?**
|
|
74
|
+
- **Blazing Fast**: Zero-copy reads by default, single bulk operations
|
|
75
|
+
- **Zero Dependencies**: Pure Python + numpy (no C++ compilation needed)
|
|
76
|
+
- **Format Support**: Uncompressed PLY + PlayCanvas compressed format
|
|
77
|
+
- **Auto-Detection**: Automatically detects format and SH degree
|
|
78
|
+
- **Production Ready**: 65 passing tests, comprehensive benchmarks, CI/CD pipeline
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Features
|
|
83
|
+
|
|
84
|
+
- **Fastest Gaussian PLY I/O**: Read 6.3x faster, write 1.4x faster than plyfile
|
|
85
|
+
- Read (default zero-copy): 8.09ms (400K Gaussians, SH0) - 49M Gaussians/sec
|
|
86
|
+
- Write (uncompressed): 8.72ms vs 12.18ms (50K Gaussians, SH3)
|
|
87
|
+
- Compressed read: 14.74ms (400K Gaussians) - 27M Gaussians/sec
|
|
88
|
+
- Compressed write: 63ms (400K Gaussians) - 6.3M Gaussians/sec with parallel processing
|
|
89
|
+
- **Zero-copy optimization**: Enabled by default for maximum performance
|
|
90
|
+
- **Zero dependencies**: Pure Python + numpy (no compilation required)
|
|
91
|
+
- **Multiple SH degrees**: Supports SH degrees 0-3 (14, 23, 38, 59 properties)
|
|
92
|
+
- **Compressed format**: PlayCanvas-compatible chunk-based compression (3.4x smaller for SH0)
|
|
93
|
+
- **Auto-format detection**: Automatically detects uncompressed vs compressed formats
|
|
94
|
+
- **Type-safe**: Full type hints for Python 3.10+
|
|
95
|
+
- **GSData container**: Named tuple for clean attribute access and tuple unpacking
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Installation
|
|
100
|
+
|
|
101
|
+
### From PyPI (coming soon)
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pip install gsply
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### From Source
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
git clone https://github.com/OpsiClear/gsply.git
|
|
111
|
+
cd gsply
|
|
112
|
+
pip install -e .
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Quick Start
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
import gsply
|
|
121
|
+
|
|
122
|
+
# Read PLY file (auto-detects format) - returns GSData container
|
|
123
|
+
# Uses fast zero-copy mode by default (6.3x faster than plyfile)
|
|
124
|
+
data = gsply.plyread("model.ply")
|
|
125
|
+
print(f"Loaded {data.means.shape[0]} Gaussians")
|
|
126
|
+
|
|
127
|
+
# Access via attributes
|
|
128
|
+
positions = data.means
|
|
129
|
+
colors = data.sh0
|
|
130
|
+
|
|
131
|
+
# Or unpack if needed (for compatibility)
|
|
132
|
+
means, scales, quats, opacities, sh0, shN = data[:6]
|
|
133
|
+
|
|
134
|
+
# Explicit zero-copy reading (default, 6.3x faster than plyfile)
|
|
135
|
+
data = gsply.plyread("model.ply", fast=True)
|
|
136
|
+
|
|
137
|
+
# Safe copy reading (if you need independent arrays)
|
|
138
|
+
data = gsply.plyread("model.ply", fast=False)
|
|
139
|
+
|
|
140
|
+
# Write uncompressed PLY file
|
|
141
|
+
gsply.plywrite("output.ply", data.means, data.scales, data.quats,
|
|
142
|
+
data.opacities, data.sh0, data.shN)
|
|
143
|
+
|
|
144
|
+
# Write compressed PLY file (saves as "output.compressed.ply", 14.5x smaller)
|
|
145
|
+
gsply.plywrite("output.ply", data.means, data.scales, data.quats,
|
|
146
|
+
data.opacities, data.sh0, data.shN, compressed=True)
|
|
147
|
+
|
|
148
|
+
# Detect format before reading
|
|
149
|
+
is_compressed, sh_degree = gsply.detect_format("model.ply")
|
|
150
|
+
print(f"Compressed: {is_compressed}, SH degree: {sh_degree}")
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## API Reference
|
|
156
|
+
|
|
157
|
+
### `plyread(file_path, fast=True)`
|
|
158
|
+
|
|
159
|
+
Read Gaussian Splatting PLY file (auto-detects format).
|
|
160
|
+
|
|
161
|
+
**Parameters:**
|
|
162
|
+
- `file_path` (str | Path): Path to PLY file
|
|
163
|
+
- `fast` (bool, optional): Use zero-copy optimization for uncompressed files. Default: True.
|
|
164
|
+
- `fast=True`: 1.65x faster, uses array views (default)
|
|
165
|
+
- `fast=False`: Safe independent copies of all arrays
|
|
166
|
+
|
|
167
|
+
**Returns:**
|
|
168
|
+
`GSData` namedtuple with Gaussian parameters:
|
|
169
|
+
- `means`: (N, 3) - Gaussian centers
|
|
170
|
+
- `scales`: (N, 3) - Log scales
|
|
171
|
+
- `quats`: (N, 4) - Rotations as quaternions (wxyz)
|
|
172
|
+
- `opacities`: (N,) - Logit opacities
|
|
173
|
+
- `sh0`: (N, 3) - DC spherical harmonics
|
|
174
|
+
- `shN`: (N, K, 3) - Higher-order SH coefficients (K=0 for degree 0, K=9 for degree 1, etc.)
|
|
175
|
+
- `base`: Base array (None for safe copies, array for zero-copy reads)
|
|
176
|
+
|
|
177
|
+
**Performance:**
|
|
178
|
+
- `fast=True`: ~2.89ms for 50K Gaussians (zero-copy views)
|
|
179
|
+
- `fast=False`: ~4.75ms for 50K Gaussians (safe copies)
|
|
180
|
+
- Speedup: 1.65x with zero-copy optimization
|
|
181
|
+
|
|
182
|
+
**Example:**
|
|
183
|
+
```python
|
|
184
|
+
# Default: fast zero-copy reading (1.65x faster)
|
|
185
|
+
data = gsply.plyread("model.ply")
|
|
186
|
+
print(f"Loaded {data.means.shape[0]} Gaussians with SH degree {data.shN.shape[1]}")
|
|
187
|
+
|
|
188
|
+
# Access via attributes
|
|
189
|
+
positions = data.means
|
|
190
|
+
colors = data.sh0
|
|
191
|
+
|
|
192
|
+
# Or unpack if needed
|
|
193
|
+
means, scales, quats, opacities, sh0, shN = data[:6]
|
|
194
|
+
|
|
195
|
+
# Safe copy reading (if you need independent arrays)
|
|
196
|
+
data = gsply.plyread("model.ply", fast=False)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
### `plywrite(file_path, means, scales, quats, opacities, sh0, shN=None, compressed=False)`
|
|
202
|
+
|
|
203
|
+
Write Gaussian Splatting PLY file.
|
|
204
|
+
|
|
205
|
+
**Parameters:**
|
|
206
|
+
- `file_path` (str | Path): Output PLY file path (auto-adjusted to `.compressed.ply` if `compressed=True`)
|
|
207
|
+
- `means` (np.ndarray): Shape (N, 3) - Gaussian centers
|
|
208
|
+
- `scales` (np.ndarray): Shape (N, 3) - Log scales
|
|
209
|
+
- `quats` (np.ndarray): Shape (N, 4) - Rotations as quaternions (wxyz)
|
|
210
|
+
- `opacities` (np.ndarray): Shape (N,) - Logit opacities
|
|
211
|
+
- `sh0` (np.ndarray): Shape (N, 3) - DC spherical harmonics
|
|
212
|
+
- `shN` (np.ndarray, optional): Shape (N, K, 3) or (N, K*3) - Higher-order SH
|
|
213
|
+
- `compressed` (bool): If True, write compressed format and auto-adjust extension
|
|
214
|
+
|
|
215
|
+
**Format Selection:**
|
|
216
|
+
- `compressed=False` or `.ply` extension -> Uncompressed format (fast)
|
|
217
|
+
- `compressed=True` -> Compressed format, saves as `.compressed.ply` automatically
|
|
218
|
+
- `.compressed.ply` or `.ply_compressed` extension -> Compressed format
|
|
219
|
+
|
|
220
|
+
**Performance:**
|
|
221
|
+
- Uncompressed: ~8ms for 400K Gaussians (49M Gaussians/sec)
|
|
222
|
+
- Compressed: ~63ms for 400K Gaussians (6.3M Gaussians/sec), 3.4x smaller files
|
|
223
|
+
|
|
224
|
+
**Example:**
|
|
225
|
+
```python
|
|
226
|
+
# Write uncompressed (fast, ~8ms for 400K Gaussians)
|
|
227
|
+
gsply.plywrite("output.ply", means, scales, quats, opacities, sh0, shN)
|
|
228
|
+
|
|
229
|
+
# Write compressed (saves as "output.compressed.ply", ~63ms, 3.4x smaller)
|
|
230
|
+
gsply.plywrite("output.ply", means, scales, quats, opacities, sh0, shN, compressed=True)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
### `detect_format(file_path)`
|
|
236
|
+
|
|
237
|
+
Detect PLY format type and SH degree.
|
|
238
|
+
|
|
239
|
+
**Parameters:**
|
|
240
|
+
- `file_path` (str | Path): Path to PLY file
|
|
241
|
+
|
|
242
|
+
**Returns:**
|
|
243
|
+
Tuple of (is_compressed, sh_degree):
|
|
244
|
+
- `is_compressed` (bool): True if compressed format
|
|
245
|
+
- `sh_degree` (int | None): 0-3 for uncompressed, None for compressed/unknown
|
|
246
|
+
|
|
247
|
+
**Example:**
|
|
248
|
+
```python
|
|
249
|
+
is_compressed, sh_degree = gsply.detect_format("model.ply")
|
|
250
|
+
if is_compressed:
|
|
251
|
+
print("Compressed PlayCanvas format")
|
|
252
|
+
else:
|
|
253
|
+
print(f"Uncompressed format with SH degree {sh_degree}")
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Performance
|
|
259
|
+
|
|
260
|
+
### Benchmark Results
|
|
261
|
+
|
|
262
|
+
**Real-World Dataset** (90 files, 36M Gaussians total, SH degree 0):
|
|
263
|
+
|
|
264
|
+
| Operation | gsply | Throughput | Details |
|
|
265
|
+
|-----------|-------|------------|---------|
|
|
266
|
+
| **Read** (uncompressed, zero-copy) | **8.09ms** | **49M Gaussians/sec** | 400K Gaussians avg |
|
|
267
|
+
| **Write** (compressed) | **63ms** | **6.3M Gaussians/sec** | 400K Gaussians, 3.4x compression |
|
|
268
|
+
| **Read** (compressed) | **14.74ms** | **27M Gaussians/sec** | Parallel decompression |
|
|
269
|
+
|
|
270
|
+
**Comparison vs Other Libraries** (50K Gaussians, SH degree 3):
|
|
271
|
+
|
|
272
|
+
| Operation | gsply | plyfile | Open3D | Winner |
|
|
273
|
+
|-----------|-------|---------|--------|--------|
|
|
274
|
+
| **Read** (zero-copy, default) | **2.89ms** | 18.23ms | 43.10ms | **gsply 6.3x faster** |
|
|
275
|
+
| **Read** (safe copies) | **4.75ms** | 18.23ms | 43.10ms | **gsply 3.8x faster** |
|
|
276
|
+
| **Write** (uncompressed) | **8.72ms** | 12.18ms | 35.69ms | **gsply 1.4x faster** |
|
|
277
|
+
|
|
278
|
+
### Why gsply is Faster
|
|
279
|
+
|
|
280
|
+
**Read Performance (6.3x speedup with zero-copy, default):**
|
|
281
|
+
- gsply: Single `np.fromfile()` + zero-copy array views (keeps base array alive)
|
|
282
|
+
- plyfile: 59 individual property accesses + column stacking + multiple copies
|
|
283
|
+
- Result: No memory copies for shN coefficients, 1.65x faster than safe copies
|
|
284
|
+
- Alternative: `fast=False` still achieves 3.8x speedup with safe independent arrays
|
|
285
|
+
|
|
286
|
+
**Write Performance (1.4x speedup):**
|
|
287
|
+
- gsply: Pre-allocated arrays + dtype optimization + direct binary write
|
|
288
|
+
- plyfile: 59 individual assignments + PLY structure overhead
|
|
289
|
+
- Result: Eliminates unnecessary copies and type conversions
|
|
290
|
+
|
|
291
|
+
**Compressed Format (with optimizations):**
|
|
292
|
+
- Read: 14.74ms for 400K Gaussians (27M Gaussians/sec) via parallel JIT decompression
|
|
293
|
+
- Write: 63ms for 400K Gaussians (6.3M Gaussians/sec) via radix sort + parallel JIT packing
|
|
294
|
+
- Optimizations: O(n) radix sort for chunk sorting, numba parallel processing for bit packing/unpacking
|
|
295
|
+
- Size: 3.4x smaller files with PlayCanvas-compatible chunk quantization
|
|
296
|
+
|
|
297
|
+
**Key Insight**: gsply's performance comes from recognizing that Gaussian Splatting PLY files follow a fixed format, allowing bulk operations and zero-copy views instead of generic PLY parsing. For details, see [docs/PERFORMANCE.md](docs/PERFORMANCE.md).
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Format Support
|
|
302
|
+
|
|
303
|
+
### Uncompressed PLY
|
|
304
|
+
|
|
305
|
+
Standard binary little-endian PLY format with Gaussian Splatting properties:
|
|
306
|
+
|
|
307
|
+
| SH Degree | Properties | Description |
|
|
308
|
+
|-----------|-----------|-------------|
|
|
309
|
+
| 0 | 14 | xyz, f_dc(3), opacity, scales(3), quats(4) |
|
|
310
|
+
| 1 | 23 | + 9 f_rest coefficients |
|
|
311
|
+
| 2 | 38 | + 24 f_rest coefficients |
|
|
312
|
+
| 3 | 59 | + 45 f_rest coefficients |
|
|
313
|
+
|
|
314
|
+
### Compressed PLY (PlayCanvas)
|
|
315
|
+
|
|
316
|
+
Chunk-based quantized format with automatic extension handling:
|
|
317
|
+
- **File extension**: Automatically saves as `.compressed.ply` when `compressed=True`
|
|
318
|
+
- **Compression ratio**: 3.4x for SH0 (3.8-14.5x depending on SH degree)
|
|
319
|
+
- **Chunk size**: 256 Gaussians per chunk
|
|
320
|
+
- **Bit-packed data**: 11-10-11 bits (position/scale), 2+10-10-10 bits (quaternion)
|
|
321
|
+
- **Parallel decompression**: 14.74ms for 400K Gaussians (27M Gaussians/sec)
|
|
322
|
+
- **Parallel compression**: 63ms for 400K Gaussians (6.3M Gaussians/sec) with radix sort
|
|
323
|
+
- **Compatible with**: PlayCanvas, SuperSplat, other WebGL viewers
|
|
324
|
+
|
|
325
|
+
For format details, see [docs/COMPRESSED_FORMAT.md](docs/COMPRESSED_FORMAT.md).
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Development
|
|
330
|
+
|
|
331
|
+
### Setup
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
# Clone repository
|
|
335
|
+
git clone https://github.com/OpsiClear/gsply.git
|
|
336
|
+
cd gsply
|
|
337
|
+
|
|
338
|
+
# Install in development mode
|
|
339
|
+
pip install -e .[dev]
|
|
340
|
+
|
|
341
|
+
# Run tests
|
|
342
|
+
pytest tests/ -v
|
|
343
|
+
|
|
344
|
+
# Run with coverage
|
|
345
|
+
pytest tests/ -v --cov=gsply --cov-report=html
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Project Structure
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
gsply/
|
|
352
|
+
├── src/
|
|
353
|
+
│ └── gsply/
|
|
354
|
+
│ ├── __init__.py # Public API
|
|
355
|
+
│ ├── reader.py # PLY reading (uncompressed + compressed)
|
|
356
|
+
│ ├── writer.py # PLY writing (uncompressed + compressed)
|
|
357
|
+
│ └── py.typed # PEP 561 type marker
|
|
358
|
+
├── tests/ # Unit tests (56 tests)
|
|
359
|
+
├── benchmarks/ # Performance benchmarks
|
|
360
|
+
├── docs/ # Documentation
|
|
361
|
+
│ ├── PERFORMANCE.md # Performance benchmarks and optimization history
|
|
362
|
+
│ ├── COMPRESSED_FORMAT.md # Compressed PLY format specification
|
|
363
|
+
│ ├── VECTORIZATION_EXPLAINED.md # Vectorization deep-dive
|
|
364
|
+
│ ├── CI_CD_SETUP.md # CI/CD pipeline documentation
|
|
365
|
+
│ ├── BUILD.md # Build and distribution guide
|
|
366
|
+
│ ├── RELEASE_NOTES.md # Release notes and version history
|
|
367
|
+
│ ├── COMPATIBILITY_FIXES.md # Format compatibility details
|
|
368
|
+
│ └── archive/ # Historical documentation
|
|
369
|
+
├── .github/ # CI/CD workflows
|
|
370
|
+
├── pyproject.toml # Package configuration
|
|
371
|
+
└── README.md # This file
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Benchmarking
|
|
377
|
+
|
|
378
|
+
Compare gsply performance against other PLY libraries:
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
# Install benchmark dependencies
|
|
382
|
+
pip install -e .[benchmark]
|
|
383
|
+
|
|
384
|
+
# Run benchmark with default settings
|
|
385
|
+
python benchmarks/benchmark.py
|
|
386
|
+
|
|
387
|
+
# Custom test file and iterations
|
|
388
|
+
python benchmarks/benchmark.py --config.file path/to/model.ply --config.iterations 20
|
|
389
|
+
|
|
390
|
+
# Skip write benchmarks
|
|
391
|
+
python benchmarks/benchmark.py --config.skip-write
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
The benchmark measures:
|
|
395
|
+
- **Read performance**: Time to load PLY file into numpy arrays
|
|
396
|
+
- **Write performance**: Time to write numpy arrays to PLY file
|
|
397
|
+
- **File sizes**: Comparison of output file sizes
|
|
398
|
+
- **Verification**: Output equivalence between libraries
|
|
399
|
+
|
|
400
|
+
Example output:
|
|
401
|
+
```
|
|
402
|
+
READ PERFORMANCE (50K Gaussians, SH degree 3)
|
|
403
|
+
Library Time Speedup
|
|
404
|
+
gsply (fast) 2.89ms baseline (FASTEST)
|
|
405
|
+
gsply (safe) 4.75ms 0.61x (1.6x slower than fast)
|
|
406
|
+
plyfile 18.23ms 0.16x (6.3x SLOWER)
|
|
407
|
+
Open3D 43.10ms 0.07x (14.9x slower)
|
|
408
|
+
|
|
409
|
+
WRITE PERFORMANCE
|
|
410
|
+
Library Time Speedup File Size
|
|
411
|
+
gsply 8.72ms baseline (FASTEST) 11.34MB
|
|
412
|
+
plyfile 12.18ms 0.72x (1.4x slower) 11.34MB
|
|
413
|
+
Open3D 35.69ms 0.24x (4.1x slower) 1.15MB (XYZ only)
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## Testing
|
|
419
|
+
|
|
420
|
+
gsply has comprehensive test coverage with 65 passing tests:
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
# Run all tests
|
|
424
|
+
pytest tests/ -v
|
|
425
|
+
|
|
426
|
+
# Run specific test file
|
|
427
|
+
pytest tests/test_reader.py -v
|
|
428
|
+
|
|
429
|
+
# Run with coverage report
|
|
430
|
+
pytest tests/ -v --cov=gsply --cov-report=html
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
Test categories:
|
|
434
|
+
- Format detection (compressed/uncompressed, SH degrees)
|
|
435
|
+
- Reading (various SH degrees, edge cases, compressed format)
|
|
436
|
+
- Writing (various SH degrees, format preservation, compressed format)
|
|
437
|
+
- Round-trip (read-write-read consistency)
|
|
438
|
+
- Error handling (invalid files, malformed data)
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
## Documentation
|
|
443
|
+
|
|
444
|
+
gsply includes comprehensive documentation covering all aspects of the library:
|
|
445
|
+
|
|
446
|
+
- **[docs/PERFORMANCE.md](docs/PERFORMANCE.md)** - Performance benchmarks, optimization history, and comparison with other libraries
|
|
447
|
+
- **[docs/COMPRESSED_FORMAT.md](docs/COMPRESSED_FORMAT.md)** - Complete compressed PLY format specification with examples
|
|
448
|
+
- **[docs/VECTORIZATION_EXPLAINED.md](docs/VECTORIZATION_EXPLAINED.md)** - Deep-dive into vectorization techniques for 38.5x speedup
|
|
449
|
+
- **[docs/BUILD.md](docs/BUILD.md)** - Build system, distribution, and packaging guide
|
|
450
|
+
- **[docs/CI_CD_SETUP.md](docs/CI_CD_SETUP.md)** - CI/CD pipeline reference and GitHub Actions workflows
|
|
451
|
+
- **[docs/RELEASE_NOTES.md](docs/RELEASE_NOTES.md)** - Release notes and version history
|
|
452
|
+
- **[docs/COMPATIBILITY_FIXES.md](docs/COMPATIBILITY_FIXES.md)** - Format compatibility details and fixes
|
|
453
|
+
- **[docs/archive/](docs/archive/)** - Historical documentation from development phases
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
## CI/CD
|
|
458
|
+
|
|
459
|
+
gsply includes a complete GitHub Actions CI/CD pipeline:
|
|
460
|
+
|
|
461
|
+
- **Multi-platform testing**: Ubuntu, Windows, macOS
|
|
462
|
+
- **Multi-version testing**: Python 3.10, 3.11, 3.12, 3.13
|
|
463
|
+
- **Automated benchmarking**: Performance tracking on PRs
|
|
464
|
+
- **Build verification**: Wheel building and installation testing
|
|
465
|
+
- **PyPI publishing**: Automated release on GitHub Release
|
|
466
|
+
|
|
467
|
+
See [docs/CI_CD_SETUP.md](docs/CI_CD_SETUP.md) for details.
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
## Contributing
|
|
472
|
+
|
|
473
|
+
Contributions are welcome! Please see [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) for guidelines.
|
|
474
|
+
|
|
475
|
+
**Quick start:**
|
|
476
|
+
1. Fork the repository
|
|
477
|
+
2. Create a feature branch
|
|
478
|
+
3. Make your changes with tests
|
|
479
|
+
4. Run tests and benchmarks
|
|
480
|
+
5. Submit a pull request
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## License
|
|
485
|
+
|
|
486
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
## Citation
|
|
491
|
+
|
|
492
|
+
If you use gsply in your research, please cite:
|
|
493
|
+
|
|
494
|
+
```bibtex
|
|
495
|
+
@software{gsply2024,
|
|
496
|
+
author = {OpsiClear},
|
|
497
|
+
title = {gsply: Ultra-Fast Gaussian Splatting PLY I/O},
|
|
498
|
+
year = {2024},
|
|
499
|
+
url = {https://github.com/OpsiClear/gsply}
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
## Related Projects
|
|
506
|
+
|
|
507
|
+
- **gsplat**: CUDA-accelerated Gaussian Splatting rasterizer
|
|
508
|
+
- **nerfstudio**: NeRF training framework with Gaussian Splatting support
|
|
509
|
+
- **PlayCanvas SuperSplat**: Web-based Gaussian Splatting viewer
|
|
510
|
+
- **3D Gaussian Splatting**: Original paper and implementation
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
|
|
514
|
+
<div align="center">
|
|
515
|
+
|
|
516
|
+
**Made with Python and numpy**
|
|
517
|
+
|
|
518
|
+
[Report Bug](https://github.com/OpsiClear/gsply/issues) | [Request Feature](https://github.com/OpsiClear/gsply/issues) | [Documentation](docs/PERFORMANCE.md)
|
|
519
|
+
|
|
520
|
+
</div>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
gsply/__init__.py,sha256=CnvuTLQBmOtFivZJKkfIPSv61Hj3_7s6Az1Z_rzalK4,2058
|
|
2
|
+
gsply/formats.py,sha256=g45h1r5bj7rM9GGlB6uL-F94vmgkZo5yJ4NA_9lEt3k,6699
|
|
3
|
+
gsply/py.typed,sha256=cZhjU4bgcfkAJgWW8rlBPwh-6sWO56Oixl8mV1RlwjI,74
|
|
4
|
+
gsply/reader.py,sha256=8DGXTGMLYsmq16iz_MdBGHGG6xSQ6kFEmLV_f1iE8Nw,32789
|
|
5
|
+
gsply/writer.py,sha256=6jQUil_I2QusKWHD7mNTT72IZirErXugHigl0-9itGM,41562
|
|
6
|
+
gsply-0.1.0.dist-info/licenses/LICENSE,sha256=x8m41gSB8q3WDvJufYbtIDp1tnNLYFX_nDSNYVOT5Mw,1066
|
|
7
|
+
gsply-0.1.0.dist-info/METADATA,sha256=UjH3un_uRM2QXXiKZkAAYTSyihQTc0KfEfC575RszQk,18350
|
|
8
|
+
gsply-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
+
gsply-0.1.0.dist-info/top_level.txt,sha256=IBdMXwfP14Y9HbLvrKWJZeHnHA5ydU3Lz38ioQt6bXo,6
|
|
10
|
+
gsply-0.1.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
11
|
+
gsply-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 OpsiClear
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
gsply
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|