Skip to content

Commit c1d0328

Browse files
committed
Initial pure Python Pipeline, Stage and descendant classes
1 parent 3b534af commit c1d0328

File tree

3 files changed

+315
-63
lines changed

3 files changed

+315
-63
lines changed

pdal/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
from .libpdalpython import Pipeline
2-
from .libpdalpython import getDimensions, getInfo
3-
41
__version__ = "2.4.2"
2+
__all__ = ["Pipeline", "Reader", "Filter", "Writer", "dimensions", "info"]
3+
4+
from .libpdalpython import getDimensions, getInfo
5+
from .pipeline import Pipeline, Reader, Filter, Writer
56

67
dimensions = getDimensions()
78
info = getInfo()

pdal/libpdalpython.pyx

Lines changed: 104 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ import json
55
from types import SimpleNamespace
66

77
from cpython.ref cimport Py_DECREF
8-
from libcpp.vector cimport vector
9-
from libcpp.string cimport string
10-
from libc.stdint cimport int64_t
118
from libcpp cimport bool
9+
from libcpp.string cimport string
10+
from libcpp.vector cimport vector
1211

1312
import numpy as np
1413
cimport numpy as np
@@ -56,6 +55,21 @@ def getDimensions():
5655
return output
5756

5857

58+
cdef extern from "pdal/StageFactory.hpp" namespace "pdal":
59+
cpdef cppclass StageFactory:
60+
@staticmethod
61+
string inferReaderDriver(string)
62+
@staticmethod
63+
string inferWriterDriver(string)
64+
65+
66+
def infer_reader_driver(driver):
67+
return StageFactory.inferReaderDriver(driver)
68+
69+
def infer_writer_driver(driver):
70+
return StageFactory.inferWriterDriver(driver)
71+
72+
5973
cdef extern from "PyArray.hpp" namespace "pdal::python":
6074
cdef cppclass Array:
6175
Array(np.ndarray) except +
@@ -65,7 +79,7 @@ cdef extern from "pdal/PipelineExecutor.hpp" namespace "pdal":
6579
cdef cppclass PipelineExecutor:
6680
PipelineExecutor(const char*) except +
6781
bool executed() except +
68-
int64_t execute() except +
82+
int execute() except +
6983
bool validate() except +
7084
string getPipeline() except +
7185
string getMetadata() except +
@@ -78,66 +92,74 @@ cdef extern from "pdal/PipelineExecutor.hpp" namespace "pdal":
7892
cdef extern from "PyPipeline.hpp" namespace "pdal::python":
7993
void readPipeline(PipelineExecutor*, string) except +
8094
void addArrayReaders(PipelineExecutor*, vector[Array *]) except +
81-
vector[np.PyArrayObject*] getArrays(const PipelineExecutor* executor) except +
82-
vector[np.PyArrayObject*] getMeshes(const PipelineExecutor* executor) except +
95+
vector[np.PyArrayObject*] getArrays(const PipelineExecutor*) except +
96+
vector[np.PyArrayObject*] getMeshes(const PipelineExecutor*) except +
8397

8498

8599
cdef class Pipeline:
86100
cdef PipelineExecutor* _executor
87-
cdef vector[Array *] _arrays;
88-
89-
def __cinit__(self, unicode json, list arrays=None):
90-
self._executor = new PipelineExecutor(json.encode('UTF-8'))
91-
readPipeline(self._executor, json.encode('UTF-8'))
92-
if arrays is not None:
93-
for array in arrays:
94-
self._arrays.push_back(new Array(array))
95-
addArrayReaders(self._executor, self._arrays)
101+
cdef vector[Array*] _inputs
96102

97103
def __dealloc__(self):
98-
for array in self._arrays:
99-
del array
100-
del self._executor
101-
102-
property pipeline:
103-
def __get__(self):
104-
return self._executor.getPipeline()
105-
106-
property metadata:
107-
def __get__(self):
108-
return self._executor.getMetadata()
109-
110-
property loglevel:
111-
def __get__(self):
112-
return self._executor.getLogLevel()
113-
def __set__(self, v):
114-
self._executor.setLogLevel(v)
115-
116-
property log:
117-
def __get__(self):
118-
return self._executor.getLog()
119-
120-
property schema:
121-
def __get__(self):
122-
return json.loads(self._executor.getSchema())
123-
124-
property arrays:
125-
def __get__(self):
126-
if not self._executor.executed():
127-
raise RuntimeError("call execute() before fetching arrays")
128-
return self._vector_to_list(getArrays(self._executor))
129-
130-
property meshes:
131-
def __get__(self):
132-
if not self._executor.executed():
133-
raise RuntimeError("call execute() before fetching the mesh")
134-
return self._vector_to_list(getMeshes(self._executor))
104+
self.inputs = []
105+
106+
def __copy__(self):
107+
cdef Pipeline clone = self.__class__()
108+
clone._inputs = self._inputs
109+
return clone
110+
111+
@property
112+
def inputs(self):
113+
raise AttributeError("unreadable attribute")
114+
115+
@inputs.setter
116+
def inputs(self, ndarrays):
117+
self._inputs.clear()
118+
for ndarray in ndarrays:
119+
self._inputs.push_back(new Array(ndarray))
120+
self._delete_executor()
121+
122+
@property
123+
def pipeline(self):
124+
return self._get_executor().getPipeline()
125+
126+
@property
127+
def metadata(self):
128+
return self._get_executor().getMetadata()
129+
130+
@property
131+
def loglevel(self):
132+
return self._get_executor().getLogLevel()
133+
134+
@loglevel.setter
135+
def loglevel(self, level):
136+
self._get_executor().setLogLevel(level)
137+
138+
@property
139+
def log(self):
140+
return self._get_executor().getLog()
141+
142+
@property
143+
def schema(self):
144+
return json.loads(self._get_executor().getSchema())
145+
146+
@property
147+
def arrays(self):
148+
if not self._get_executor().executed():
149+
raise RuntimeError("call execute() before fetching arrays")
150+
return _vector_to_list(getArrays(self._executor))
151+
152+
@property
153+
def meshes(self):
154+
if not self._get_executor().executed():
155+
raise RuntimeError("call execute() before fetching the mesh")
156+
return _vector_to_list(getMeshes(self._executor))
135157

136158
def execute(self):
137-
return self._executor.execute()
159+
return self._get_executor().execute()
138160

139161
def validate(self):
140-
return self._executor.validate()
162+
return self._get_executor().validate()
141163

142164
def get_meshio(self, idx):
143165
try:
@@ -155,9 +177,31 @@ cdef class Pipeline:
155177
[("triangle", np.stack((mesh["A"], mesh["B"], mesh["C"]), 1))],
156178
)
157179

158-
cdef _vector_to_list(self, vector[np.PyArrayObject*] arrays):
159-
output = []
160-
for array in arrays:
161-
output.append(<object>array)
162-
Py_DECREF(output[-1])
163-
return output
180+
@property
181+
def _json(self):
182+
raise NotImplementedError("Abstract property")
183+
184+
@property
185+
def _num_inputs(self):
186+
return self._inputs.size()
187+
188+
def _delete_executor(self):
189+
if self._executor:
190+
del self._executor
191+
self._executor = NULL
192+
193+
cdef PipelineExecutor* _get_executor(self) except NULL:
194+
if not self._executor:
195+
json_bytes = self._json.encode("UTF-8")
196+
self._executor = new PipelineExecutor(json_bytes)
197+
readPipeline(self._executor, json_bytes)
198+
addArrayReaders(self._executor, self._inputs)
199+
return self._executor
200+
201+
202+
cdef _vector_to_list(vector[np.PyArrayObject*] arrays):
203+
output = []
204+
for array in arrays:
205+
output.append(<object>array)
206+
Py_DECREF(output[-1])
207+
return output

0 commit comments

Comments
 (0)