1 # #distutils: language=c++
2 #from cython.operator cimport dereference as deref
3 from libcpp.vector cimport vector
4 from libcpp.map cimport map
5 from libcpp.string cimport string
6 from ..ie_api cimport IENetwork, BlobBuffer
7 from .cimport dnn_builder_impl_defs as C
8 from .dnn_builder_impl_defs cimport Blob
21 cdef class NetworkBuilder:
22 def __cinit__(self, name=None, IENetwork ie_net=None):
23 if name is not None and ie_net is not None:
24 raise AttributeError("Both name and ie_net arguments are defined")
25 elif name is not None:
26 self.impl = C.NetworkBuilder(name.encode())
27 elif ie_net is not None:
28 self.impl = C.NetworkBuilder().from_ie_network(ie_net.impl)
31 cdef INetwork i_net = INetwork()
32 i_net.impl = self.impl.build()
35 def get_layer(self, id: int):
36 cdef LayerBuilder py_layer = LayerBuilder()
37 py_layer.impl = self.impl.getLayer(id)
42 cdef vector[C.LayerBuilder] c_layers = self.impl.getLayers()
43 cdef LayerBuilder py_layer
46 py_layer = LayerBuilder()
48 py_layers[l.getName().decode()] = py_layer
51 def remove_layer(self, LayerBuilder layer):
52 self.impl.removeLayer(layer.impl)
54 def get_layer_connection(self, LayerBuilder layer):
55 cdef vector[C.Connection] c_connections = self.impl.getLayerConnections(layer.impl)
56 cdef Connection connection
58 for con in c_connections:
59 connection = Connection()
61 connections.append(connection)
64 def disconnect(self, Connection connection):
65 self.impl.disconnect(connection.impl)
67 def connect(self, PortInfo input, PortInfo output):
68 self.impl.connect(input.impl, output.impl)
70 def add_layer(self, LayerBuilder layer, input_ports: list = None):
71 cdef vector[C.PortInfo] c_ports
74 return self.impl.addLayer(layer.impl)
77 c_port = PortInfo(p.layer_id, p.port_id)
78 c_ports.push_back(c_port.impl)
79 return self.impl.addAndConnectLayer(c_ports, layer.impl)
85 cdef vector[C.ILayer] c_layers = self.impl.layers
96 cdef vector[C.ILayer] c_layers = self.impl.layers
100 layers[l.name.decode()] = layer
107 cdef vector[C.ILayer] c_layers = self.impl.inputs
111 layers[l.name.decode()] = layer
118 cdef vector[C.ILayer] c_layers = self.impl.outputs
122 layers[l.name.decode()] = layer
127 return self.impl.name.decode()
132 return self.impl.size
134 def get_layer_connection(self, layer: ILayer):
135 cdef Connection connection
137 cdef vector[C.Connection] c_connections = self.impl.getLayerConnections(layer.id)
138 for con in c_connections:
139 connection = Connection()
140 connection.impl = con
141 connections.append(connection)
144 def to_ie_network(self):
145 cdef IENetwork net = IENetwork()
146 net.impl = self.impl.to_ie_network()
152 return self.impl.name.decode()
160 return self.impl.type.decode()
164 return {k.decode(): v.decode() for k, v in self.impl.parameters}
167 def input_ports(self):
169 cdef vector[C.Port] c_ports = self.impl.in_ports
178 def output_ports(self):
180 cdef vector[C.Port] c_ports = self.impl.out_ports
189 def constant_data(self):
190 cdef map[string, Blob.Ptr] c_constant_data
191 c_constant_data = self.impl.constant_data
193 cdef BlobBuffer weights_buffer
194 for weights in c_constant_data:
195 weights_buffer = BlobBuffer()
196 weights_buffer.reset(weights.second)
197 constant_data[weights.first.decode()] = weights_buffer.to_numpy()
202 def __cinit__(self, shape: list=[]):
203 cdef vector[size_t] c_shape
206 self.impl = C.Port(c_shape)
209 return self.impl.shape
212 def __cinit__(self, layer_id: int = -1, port_id: int = -1):
213 if layer_id != -1 and port_id != -1:
214 self.impl = C.PortInfo(layer_id, port_id)
216 self.impl = C.PortInfo()
219 return self.impl.layer_id
223 return self.impl.port_id
225 def __eq__(self, other):
226 return self.layer_id == other.layer_id and self.port_id == other.port_id
228 def __ne__(self, other):
229 return self.layer_id != other.layer_id and self.port_id != other.port_id
231 cdef class Connection:
232 def __cinit__(self, PortInfo input = None, PortInfo output = None):
234 self.impl = C.Connection(input.impl, output.impl)
236 self.impl = C.Connection()
239 cdef PortInfo port_info = PortInfo()
240 port_info.impl = self.impl._from
245 cdef PortInfo port_info = PortInfo()
246 port_info.impl = self.impl.to
249 def __eq__(self, other):
250 return self._from == other._from and self.to == other.to
252 def __ne__(self, other):
253 return self._from != other._from and self.to != other.to
256 def check_constant_data(data):
257 for k, v in data.items():
258 if not all([isinstance(x, type(v[0])) for x in v]):
259 raise TypeError("Elements of list for key {} have different data types! "
260 "Please specify list of 'int' or 'float' values.".format(k))
261 if isinstance(v, list):
262 if isinstance(v[0], float):
264 elif isinstance(v[0], int):
267 raise TypeError("Unsupported precision of the data for key {}! Given {} but 'float or 'int' precision expected".
268 format(k, str(v.dtype)))
269 data[k] = np.asanyarray(v, dtype=dtype)
270 elif isinstance(v, np.ndarray):
273 raise TypeError("Unsupported data type for key '{}'. {} given but 'list' or 'numpy.ndarray' expected".
278 # TODO: Fix LAyerBuilder object copying - pass by reference
279 # cdef class LayerConstantData(dict):
280 # def update(self, other=None, **kwargs):
282 # other = check_constant_data(other)
283 # cdef vector[size_t] dims
284 # cdef Blob.Ptr blob_ptr
285 # cdef BlobBuffer buffer
286 # for k, v in other.items():
287 # if k in self.keys() and (v.shape == self[k].shape and v.dtype == self[k].dtype):
288 # print("Reuse blob for {}\n".format(k))
291 # for dim in v.shape:
292 # dims.push_back(dim)
293 # ie_precision = np_precision_map.get(str(v.dtype), None)
294 # if not ie_precision:
295 # raise BufferError("Unsupported precision of the data for key {}! Given {} but one of the {} precisions expected".
296 # format(k, str(v.dtype), ", ".join(np_precision_map.keys())))
297 # blob_ptr = deref(self.impl).allocateBlob(dims, ie_precision.encode())
298 # buffer = BlobBuffer()
299 # buffer.reset(blob_ptr)
300 # np_buffer = buffer.to_numpy()
302 # deref(self.impl).addConstantData(k.encode(), blob_ptr)
304 cdef class LayerBuilder:
306 def __cinit__(self, type: str=None, name: str=None):
308 self.impl = C.LayerBuilder(name.encode(), type.encode())
310 self.impl = C.LayerBuilder()
317 return self.impl.getName().decode()
319 def name(self, name: str):
320 self.impl.setName(name.encode())
324 return self.impl.getType().decode()
326 def type(self, type: str):
327 self.impl.setType(type.encode())
330 def input_ports(self):
332 cdef vector[C.Port] c_ports = self.impl.getInputPorts()
337 py_ports.append(port)
341 def input_ports(self, ports: list):
342 cdef vector[C.Port] c_ports
345 c_port = Port(p.shape)
346 c_ports.push_back(c_port.impl)
347 self.impl.setInputPorts(c_ports)
350 def output_ports(self):
352 cdef vector[C.Port] c_ports = self.impl.getOutputPorts()
357 py_ports.append(port)
361 def output_ports(self, ports: list):
362 cdef vector[C.Port] c_ports
365 c_port = Port(p.shape)
366 c_ports.push_back(c_port.impl)
367 self.impl.setOutputPorts(c_ports)
371 return {k.decode(): v.decode() for k, v in self.impl.getParameters()}
374 def params(self, params_map: dict):
375 cdef map[string, string] c_params_map
376 for k, v in params_map.items():
377 c_params_map[k.encode()] = str(v).encode()
378 self.impl.setParameters(c_params_map)
381 cdef ILayer layer = ILayer()
382 layer.impl = self.impl.build()
386 def constant_data(self):
387 cdef map[string, Blob.Ptr] c_constant_data
388 c_constant_data = self.impl.getConstantData()
390 # TODO: Fix LAyerBuilder object copying - pass by reference
391 # constant_data = LayerConstantData()
392 # constant_data.impl = make_shared[C.LayerBuilder](self.impl)
393 cdef BlobBuffer weights_buffer
394 for weights in c_constant_data:
395 weights_buffer = BlobBuffer()
396 weights_buffer.reset(weights.second)
397 constant_data[weights.first.decode()] = weights_buffer.to_numpy()
400 @constant_data.setter
401 def constant_data(self, data: dict):
402 cdef vector[size_t] dims
403 cdef map[string, Blob.Ptr] c_constant_data
404 cdef Blob.Ptr blob_ptr
405 cdef BlobBuffer buffer
406 data = check_constant_data(data)
407 for k, v in data.items():
410 ie_precision = np_precision_map.get(str(v.dtype), None)
412 raise BufferError("Unsupported precision of the data for key {}! Given {} but one of the {} precisions expected".
413 format(k, str(v.dtype), ", ".join(np_precision_map.keys())))
414 blob_ptr = self.impl.allocateBlob(dims, ie_precision.encode())
415 buffer = BlobBuffer()
416 buffer.reset(blob_ptr)
417 np_buffer = buffer.to_numpy()
419 c_constant_data[k.encode()] = blob_ptr
421 self.impl.setConstantData(c_constant_data)
423 # TODO: Implement get\setGraph when will be supported