ansys-pyensight-core 0.9.0__tar.gz → 0.9.1__tar.gz

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.

Potentially problematic release.


This version of ansys-pyensight-core might be problematic. Click here for more details.

Files changed (36) hide show
  1. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/PKG-INFO +2 -2
  2. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/pyproject.toml +2 -2
  3. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/renderable.py +6 -1
  4. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/session.py +3 -1
  5. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/dsg_server.py +16 -0
  6. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/omniverse.py +18 -2
  7. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/omniverse_glb_server.py +150 -19
  8. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/LICENSE +0 -0
  9. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/README.rst +0 -0
  10. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/__init__.py +0 -0
  11. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/common.py +0 -0
  12. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/deep_pixel_view.html +0 -0
  13. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/dockerlauncher.py +0 -0
  14. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/enscontext.py +0 -0
  15. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/enshell_grpc.py +0 -0
  16. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/ensight_grpc.py +0 -0
  17. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/ensobj.py +0 -0
  18. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/launch_ensight.py +0 -0
  19. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/launcher.py +0 -0
  20. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/libuserd.py +0 -0
  21. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/listobj.py +0 -0
  22. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/locallauncher.py +0 -0
  23. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/py.typed +0 -0
  24. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/sgeo_poll.html +0 -0
  25. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/__init__.py +0 -0
  26. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/adr.py +0 -0
  27. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/export.py +0 -0
  28. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/omniverse_cli.py +0 -0
  29. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/omniverse_dsg_server.py +0 -0
  30. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/parts.py +0 -0
  31. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/query.py +0 -0
  32. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/readers.py +0 -0
  33. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/resources/Materials/000_sky.exr +0 -0
  34. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/support.py +0 -0
  35. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/variables.py +0 -0
  36. {ansys_pyensight_core-0.9.0 → ansys_pyensight_core-0.9.1}/src/ansys/pyensight/core/utils/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: ansys-pyensight-core
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: A python wrapper for Ansys EnSight
5
5
  Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
6
6
  Maintainer-email: "ANSYS, Inc." <pyansys.core@ansys.com>
@@ -20,7 +20,7 @@ Requires-Dist: ansys-api-pyensight==0.4.2
20
20
  Requires-Dist: requests>=2.28.2
21
21
  Requires-Dist: docker>=6.1.0
22
22
  Requires-Dist: urllib3<3.0.0
23
- Requires-Dist: numpy>=1.21.0,<2
23
+ Requires-Dist: numpy>=1.21.0,<3
24
24
  Requires-Dist: Pillow>=9.3.0
25
25
  Requires-Dist: pypng>=0.0.20
26
26
  Requires-Dist: psutil>=5.9.2
@@ -6,7 +6,7 @@ build-backend = "flit_core.buildapi"
6
6
 
7
7
  [project]
8
8
  name = "ansys-pyensight-core"
9
- version = "0.9.0"
9
+ version = "0.9.1"
10
10
  description = "A python wrapper for Ansys EnSight"
11
11
  readme = "README.rst"
12
12
  requires-python = ">=3.9,<4"
@@ -31,7 +31,7 @@ dependencies = [
31
31
  "requests>=2.28.2",
32
32
  "docker>=6.1.0",
33
33
  "urllib3<3.0.0",
34
- "numpy>=1.21.0,<2",
34
+ "numpy>=1.21.0,<3",
35
35
  "Pillow>=9.3.0",
36
36
  "pypng>=0.0.20",
37
37
  "psutil>=5.9.2",
@@ -557,7 +557,11 @@ class RenderableVNC(Renderable):
557
557
  """Generates an ansys-nexus-viewer component that can be used to connect to the EnSight VNC remote image renderer."""
558
558
 
559
559
  def __init__(self, *args, **kwargs) -> None:
560
+ ui = kwargs.get("ui")
561
+ if kwargs.get("ui"):
562
+ kwargs.pop("ui")
560
563
  super().__init__(*args, **kwargs)
564
+ self._ui = ui
561
565
  self._generate_url()
562
566
  self._rendertype = "remote"
563
567
  self.update()
@@ -585,6 +589,7 @@ class RenderableVNC(Renderable):
585
589
  """
586
590
  optional_query = self._get_query_parameters_str()
587
591
  version = _get_ansysnexus_version(self._session._cei_suffix)
592
+ ui = "simple" if not self._ui else self._ui
588
593
  if int(self._session._cei_suffix) < 242: # pragma: no cover
589
594
  version = ""
590
595
  self._update_2023R2_or_less() # pragma: no cover
@@ -604,7 +609,7 @@ class RenderableVNC(Renderable):
604
609
  query_args = f', "extra_query_args":"{optional_query[1:]}"' # pragma: no cover
605
610
 
606
611
  attributes = ' renderer="envnc"'
607
- attributes += ' ui="simple"'
612
+ attributes += f" ui={ui}"
608
613
  attributes += ' active="true"'
609
614
  attributes += (
610
615
  " renderer_options='"
@@ -838,6 +838,7 @@ class Session:
838
838
  aa: int = 4,
839
839
  fps: float = 30.0,
840
840
  num_frames: Optional[int] = None,
841
+ ui: Optional[str] = "simple",
841
842
  ) -> "renderable.Renderable":
842
843
  """Capture the current EnSight scene or otherwise make it available for
843
844
  display in a web browser.
@@ -898,7 +899,7 @@ class Session:
898
899
  if self._html_port is None:
899
900
  raise RuntimeError("No websocketserver has been associated with this Session")
900
901
 
901
- kwargs = dict(
902
+ kwargs: Dict[str, Union[float, int, None, str]] = dict(
902
903
  height=height, width=width, temporal=temporal, aa=aa, fps=fps, num_frames=num_frames
903
904
  )
904
905
  if self._jupyter_notebook: # pragma: no cover
@@ -924,6 +925,7 @@ class Session:
924
925
  else:
925
926
  render = RenderableSGEO(self, **kwargs)
926
927
  elif what == "remote":
928
+ kwargs["ui"] = ui
927
929
  render = RenderableVNC(self, **kwargs)
928
930
  elif what == "remote_scene":
929
931
  render = RenderableEVSN(self, **kwargs)
@@ -685,6 +685,9 @@ class DSGSession(object):
685
685
  self._dsg_queue: Optional[queue.SimpleQueue] = None # Outgoing messages to EnSight
686
686
  self._shutdown = False
687
687
  self._dsg = None
688
+ # Prevent the protobuffer queue from growing w/o limits. The payload chunking is
689
+ # around 4MB, so 200 buffers would be a bit less than 1GB.
690
+ self._max_dsg_queue_size = int(os.environ.get("ANSYS_OV_SERVER_MAX_GRPC_QUEUE_SIZE", "200"))
688
691
  self._normalize_geometry = normalize_geometry
689
692
  self._vrmode = vrmode
690
693
  self._time_scale = time_scale
@@ -711,6 +714,14 @@ class DSGSession(object):
711
714
  def mesh_block_count(self) -> int:
712
715
  return self._mesh_block_count
713
716
 
717
+ @property
718
+ def max_dsg_queue_size(self) -> int:
719
+ return self._max_dsg_queue_size
720
+
721
+ @max_dsg_queue_size.setter
722
+ def max_dsg_queue_size(self, value: int) -> None:
723
+ self._max_dsg_queue_size = value
724
+
714
725
  @property
715
726
  def vrmode(self) -> bool:
716
727
  return self._vrmode
@@ -891,6 +902,11 @@ class DSGSession(object):
891
902
  while not self._shutdown:
892
903
  try:
893
904
  self._message_queue.put(next(self._dsg)) # type:ignore
905
+ # if the queue is getting too deep, wait a bit to avoid holding too
906
+ # many messages (filling up memory)
907
+ if self.max_dsg_queue_size:
908
+ while self._message_queue.qsize() >= self.max_dsg_queue_size:
909
+ time.sleep(0.001)
894
910
  except Exception:
895
911
  self._shutdown = True
896
912
  self.log("DSG connection broken, calling exit")
@@ -190,6 +190,7 @@ class Omniverse:
190
190
  live: bool = True,
191
191
  debug_filename: str = "",
192
192
  time_scale: float = 1.0,
193
+ line_width: float = 0.0,
193
194
  options: dict = {},
194
195
  ) -> None:
195
196
  """Ensure that an EnSight dsg -> omniverse server is running
@@ -224,6 +225,9 @@ class Omniverse:
224
225
  If the name of a file is provided, it will be used to save logging information on
225
226
  the connection between EnSight and Omniverse. This option is no longer supported,
226
227
  but the API remains for backwards compatibility.
228
+ line_width : float
229
+ If set, line objects will be represented as "tubes" of the size specified by
230
+ this factor. The default is 0.0 and causes lines not to be exported.
227
231
  options : dict
228
232
  Allows for a fallback for the grpc host/port and the security token.
229
233
  """
@@ -259,6 +263,8 @@ class Omniverse:
259
263
  cmd.extend(["--normalize_geometry", "true"])
260
264
  if time_scale != 1.0:
261
265
  cmd.extend(["--time_scale", str(time_scale)])
266
+ if line_width != 0.0:
267
+ cmd.extend(["--line_width", str(line_width)])
262
268
  if not live:
263
269
  cmd.extend(["--oneshot", "1"])
264
270
  cmd.extend(["--dsg_uri", dsg_uri])
@@ -336,7 +342,7 @@ class Omniverse:
336
342
  self._server_pid = None
337
343
  self._new_status_file(new=False)
338
344
 
339
- def update(self, temporal: bool = False) -> None:
345
+ def update(self, temporal: bool = False, line_width: float = 0.0) -> None:
340
346
  """Update the geometry in Omniverse
341
347
 
342
348
  Export the current EnSight scene to the current Omniverse connection.
@@ -345,10 +351,20 @@ class Omniverse:
345
351
  ----------
346
352
  temporal : bool
347
353
  If True, export all timesteps.
354
+ line_width : float
355
+ If set to a non-zero value, lines will be exported with this thickness.
356
+ This feature is only available in 2025 R2 and later.
348
357
  """
349
358
  update_cmd = "dynamicscenegraph://localhost/client/update"
359
+ prefix = "?"
350
360
  if temporal:
351
- update_cmd += "?timesteps=1"
361
+ update_cmd += f"{prefix}timesteps=1"
362
+ prefix = "&"
363
+ if line_width != 0.0:
364
+ # only in 2025 R2 and beyond
365
+ if self._ensight._session.ensight_version_check("2025 R2", exception=False):
366
+ update_cmd += f"{prefix}line_width={line_width}"
367
+ prefix = "&"
352
368
  self._check_modules()
353
369
  if not self.is_running_omniverse():
354
370
  raise RuntimeError("No Omniverse server connection is currently active.")
@@ -132,40 +132,44 @@ class GLBSession(dsg_server.DSGSession):
132
132
  """
133
133
  mesh = self._gltf.meshes[meshid]
134
134
  for prim_idx, prim in enumerate(mesh.primitives):
135
- # POINTS, LINES, LINE_LOOP, LINE_STRIP, TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN
135
+ # TODO: line width/point size
136
+ # POINTS, LINES, TRIANGLES, LINE_LOOP, LINE_STRIP, TRIANGLE_STRIP, TRIANGLE_FAN
136
137
  mode = prim.mode
137
- if mode not in (pygltflib.TRIANGLES, pygltflib.LINES, pygltflib.POINTS):
138
- self.warn(
139
- f"Unhandled connectivity {mode}. Currently only TRIANGLE and LINE connectivity is supported."
140
- )
138
+ if mode not in (
139
+ pygltflib.TRIANGLES,
140
+ pygltflib.LINES,
141
+ pygltflib.POINTS,
142
+ pygltflib.LINE_LOOP,
143
+ pygltflib.LINE_STRIP,
144
+ pygltflib.TRIANGLE_STRIP,
145
+ pygltflib.TRIANGLE_FAN,
146
+ ):
147
+ self.warn(f"Unhandled connectivity detected: {mode}. Geometry skipped.")
141
148
  continue
142
149
  glb_materialid = prim.material
143
150
 
151
+ line_width = self._callback_handler._omni.line_width
152
+ # TODO: override from scene extension: ANSYS_linewidth
153
+
144
154
  # GLB Prim -> DSG Part
145
155
  part_name = f"{parentname}_prim{prim_idx}_"
146
156
  cmd, part_pb = self._create_pb("PART", parent_id=parentid, name=part_name)
147
- part_pb.render = dynamic_scene_graph_pb2.UpdatePart.RenderingMode.CONNECTIVITY
157
+ if mode == pygltflib.POINTS:
158
+ part_pb.render = dynamic_scene_graph_pb2.UpdatePart.RenderingMode.NODES
159
+ part_pb.node_size_default = line_width
160
+ else:
161
+ part_pb.render = dynamic_scene_graph_pb2.UpdatePart.RenderingMode.CONNECTIVITY
148
162
  part_pb.shading = dynamic_scene_graph_pb2.UpdatePart.ShadingMode.NODAL
149
163
  self._map_material(glb_materialid, part_pb)
150
164
  part_dsg_id = part_pb.id
151
165
  self._handle_update_command(cmd)
152
166
 
153
167
  # GLB Attributes -> DSG Geom
154
- conn = self._get_data(prim.indices, 0)
155
- cmd, conn_pb = self._create_pb("GEOM", parent_id=part_dsg_id)
156
- if mode == pygltflib.TRIANGLES:
157
- conn_pb.payload_type = dynamic_scene_graph_pb2.UpdateGeom.ArrayType.TRIANGLES
158
- elif mode == pygltflib.LINES:
159
- conn_pb.payload_type = dynamic_scene_graph_pb2.UpdateGeom.ArrayType.LINES
160
- else:
161
- conn_pb.payload_type = dynamic_scene_graph_pb2.UpdateGeom.ArrayType.POINTS
162
- conn_pb.int_array.extend(conn)
163
- conn_pb.chunk_offset = 0
164
- conn_pb.total_array_size = len(conn)
165
- self._handle_update_command(cmd)
166
-
168
+ # Verts
169
+ num_verts = 0
167
170
  if prim.attributes.POSITION is not None:
168
171
  verts = self._get_data(prim.attributes.POSITION)
172
+ num_verts = len(verts) // 3
169
173
  cmd, verts_pb = self._create_pb("GEOM", parent_id=part_dsg_id)
170
174
  verts_pb.payload_type = dynamic_scene_graph_pb2.UpdateGeom.ArrayType.COORDINATES
171
175
  verts_pb.flt_array.extend(verts)
@@ -173,6 +177,35 @@ class GLBSession(dsg_server.DSGSession):
173
177
  verts_pb.total_array_size = len(verts)
174
178
  self._handle_update_command(cmd)
175
179
 
180
+ # Connectivity
181
+ if num_verts and (mode != pygltflib.POINTS):
182
+ if prim.indices is not None:
183
+ conn = self._get_data(prim.indices, 0)
184
+ else:
185
+ conn = numpy.array(list(range(num_verts)), dtype=numpy.uint32)
186
+ cmd, conn_pb = self._create_pb("GEOM", parent_id=part_dsg_id)
187
+ if mode == pygltflib.TRIANGLES:
188
+ conn_pb.payload_type = dynamic_scene_graph_pb2.UpdateGeom.ArrayType.TRIANGLES
189
+ elif mode == pygltflib.TRIANGLE_STRIP:
190
+ conn_pb.payload_type = dynamic_scene_graph_pb2.UpdateGeom.ArrayType.TRIANGLES
191
+ conn = self._tri_strip_to_tris(conn)
192
+ elif mode == pygltflib.TRIANGLE_FAN:
193
+ conn_pb.payload_type = dynamic_scene_graph_pb2.UpdateGeom.ArrayType.TRIANGLES
194
+ conn = self._tri_fan_to_tris(conn)
195
+ elif mode == pygltflib.LINES:
196
+ conn_pb.payload_type = dynamic_scene_graph_pb2.UpdateGeom.ArrayType.LINES
197
+ elif mode == pygltflib.LINE_LOOP:
198
+ conn_pb.payload_type = dynamic_scene_graph_pb2.UpdateGeom.ArrayType.LINES
199
+ conn = self._line_loop_to_lines(conn)
200
+ elif mode == pygltflib.LINE_STRIP:
201
+ conn_pb.payload_type = dynamic_scene_graph_pb2.UpdateGeom.ArrayType.LINES
202
+ conn = self._line_strip_to_lines(conn)
203
+ conn_pb.int_array.extend(conn)
204
+ conn_pb.chunk_offset = 0
205
+ conn_pb.total_array_size = len(conn)
206
+ self._handle_update_command(cmd)
207
+
208
+ # Normals
176
209
  if prim.attributes.NORMAL is not None:
177
210
  normals = self._get_data(prim.attributes.NORMAL)
178
211
  cmd, normals_pb = self._create_pb("GEOM", parent_id=part_dsg_id)
@@ -182,6 +215,7 @@ class GLBSession(dsg_server.DSGSession):
182
215
  normals_pb.total_array_size = len(normals)
183
216
  self._handle_update_command(cmd)
184
217
 
218
+ # Texture coords
185
219
  if prim.attributes.TEXCOORD_0 is not None:
186
220
  # Note: texture coords are stored as VEC2, so we get 2 components back
187
221
  texcoords = self._get_data(prim.attributes.TEXCOORD_0, components=2)
@@ -199,6 +233,103 @@ class GLBSession(dsg_server.DSGSession):
199
233
  texcoords_pb.variable_id = glb_varid
200
234
  self._handle_update_command(cmd)
201
235
 
236
+ @staticmethod
237
+ def _tri_strip_to_tris(conn: numpy.ndarray) -> numpy.ndarray:
238
+ """
239
+ Convert GL_TRIANGLE_STRIP connectivity into GL_TRIANGLES
240
+
241
+ Parameters
242
+ ----------
243
+ conn: numpy.ndarray
244
+ The tri strip connectivity
245
+
246
+ Returns
247
+ -------
248
+ numpy.array:
249
+ Triangles connectivity
250
+ """
251
+ tris = []
252
+ swap = False
253
+ for i in range(len(conn) - 2):
254
+ tris.append(conn[i])
255
+ if swap:
256
+ tris.append(conn[i + 2])
257
+ tris.append(conn[i + 1])
258
+ else:
259
+ tris.append(conn[i + 1])
260
+ tris.append(conn[i + 2])
261
+ swap = not swap
262
+ return numpy.array(tris, dtype=conn.dtype)
263
+
264
+ @staticmethod
265
+ def _tri_fan_to_tris(conn: numpy.ndarray) -> numpy.ndarray:
266
+ """
267
+ Convert GL_TRIANGLE_FAN connectivity into GL_TRIANGLES
268
+
269
+ Parameters
270
+ ----------
271
+ conn: numpy.ndarray
272
+ The fan connectivity
273
+
274
+ Returns
275
+ -------
276
+ numpy.array:
277
+ Triangles connectivity
278
+ """
279
+ tris = []
280
+ for i in range(1, len(conn) - 1):
281
+ tris.append(conn[0])
282
+ tris.append(conn[i])
283
+ tris.append(conn[i + 1])
284
+ return numpy.array(tris, dtype=conn.dtype)
285
+
286
+ @staticmethod
287
+ def _line_strip_to_lines(conn) -> numpy.ndarray:
288
+ """
289
+ Convert GL_LINE_STRIP connectivity into GL_LINES
290
+
291
+ Parameters
292
+ ----------
293
+ conn: numpy.ndarray
294
+ The line strip connectivity
295
+
296
+ Returns
297
+ -------
298
+ numpy.array:
299
+ Lines connectivity
300
+ """
301
+ lines = []
302
+ num_nodes = len(conn)
303
+ for i in range(num_nodes - 1):
304
+ lines.append(conn[i])
305
+ lines.append(conn[i + 1])
306
+ return numpy.array(lines, dtype=conn.dtype)
307
+
308
+ @staticmethod
309
+ def _line_loop_to_lines(conn) -> numpy.ndarray:
310
+ """
311
+ Convert GL_LINE_LOOP connectivity into GL_LINES
312
+
313
+ Parameters
314
+ ----------
315
+ conn: numpy.ndarray
316
+ The line loop connectivity
317
+
318
+ Returns
319
+ -------
320
+ numpy.array:
321
+ Lines connectivity
322
+ """
323
+ lines = []
324
+ num_nodes = len(conn)
325
+ for i in range(num_nodes):
326
+ lines.append(conn[i])
327
+ if i + 1 == num_nodes:
328
+ lines.append(conn[0])
329
+ else:
330
+ lines.append(conn[i + 1])
331
+ return numpy.array(lines, dtype=conn.dtype)
332
+
202
333
  def _get_data(
203
334
  self,
204
335
  accessorid: int,