Reading mesh files¶
To read a 2DM mesh file, instantiate a py2dm.Reader
and pass it the path of the 2DM file to read.
The preferred way to use this class is via the context manager interface:
>>> with py2dm.Reader('path/to/mesh.2dm') as mesh:
... print(mesh)
...
Py2DM Reader
5 nodes
4 elements
2 node strings
Basic usage¶
Metadata¶
The py2dm.Reader
class exposes properties for the node, element, node string, and element material count of a mesh via its num_*
and materials_per_element
properties.
Additionally, the py2dm.Reader.extent
property allows finding the extreme X and Y values of a mesh. While this method is expensive for large meshes as it checks the entire list of nodes, it is also cached, meaning that subsequent calls will reuse the first value:
with py2dm.Reader('path/to/mesh.2dm') as mesh:
start = time.time()
_ = mesh.extent
print(time.time() - start) # ~1.6 seconds
start = time.time()
_ = mesh.extent
print(time.time() - start) # ~0.0 seconds
Sequential access¶
When retrieving mesh entities in bulk, it is generally recommended using the iterator factory methods py2dm.Reader.iter_nodes()
, py2dm.Reader.iter_elements()
, and py2dm.Reader.iter_node_strings()
.
As a shorthand, you can also use the py2dm.Reader.nodes
, py2dm.Reader.elements
, and py2dm.Reader.node_strings
properties respectively. These behave exactly the same as if the corresponding iterator were called with default arguments.
>>> with py2dm.Reader('path/to/mesh.2dm') as mesh:
... for node in mesh.nodes:
... if node.id % 10 == 0:
... print(node)
...
Node #10: (1200.0, 200.0, 20.0)
Node #20: (1120.0, 220.0, 10.0)
(...)
Random access¶
To access elements randomly (i.e. by their unique ID), you can use the py2dm.Reader.node()
, py2dm.Reader.element()
, and py2dm.Reader.node_string()
methods.
Note that these use the unique identifier for a given entity. For nodes and elements, this is their ID. For node strings, this would be their unique ID when using a subformat that supports unique identifiers for node strings.
Reader class interface¶
-
class
py2dm.
Reader
¶ Default Py2DM reader class used to parse and validate 2DM files.
This reader loads the entire mesh file into memory, allowing for fast ID-based access and iteration without needing to wait for the storage medium.
Do note that this implementation also keeps the Python representation of all mesh entities in memory until the instance is destroyed, which can consume a significant amount of memory for very large meshes.
-
__init__
(self, filepath: str, **kwargs) → None¶ Instantiate a new reader for filepath.
- Parameters
filepath (
str
|pathlib.Path
) – Path to the mesh file to open.encoding (
str
) – Encoding to use when reading the file.
-
name
: str¶ Display name of the mesh.
If the
GM "<name>"
orMESHNAME "<name>"
cards are provided, their specified name will be used here. If neither card is given, the mesh name will default toUnnamed mesh
.- Type
-
property
closed
¶ Return whether the underlying file is closed.
After closing (either via the
close()
method or by leaving the reader’s context manager), any operations requiring use of the underlying file will raise apy2dm.errors.FileIsClosedError
.- Type
-
property
elements
¶ Return an iterator over all elements in the mesh.
This is synonymous to calling
py2dm.Reader.iter_elements()
with default arguments.If you prefer a list of elements, cast this iterator to
list
.with py2dm.Reader('mesh.2dm') as mesh: elements = list(mesh.elements)
- Yield
Elements from the mesh in order.
- Type
-
property
nodes
¶ Return an iterator over all nodes in the mesh.
This is synonymous to calling
py2dm.Reader.iter_nodes()
with default arguments.If you prefer a list of nodes, cast this iterator to
list
.with py2dm.Reader('mesh.2dm') as mesh: nodes = list(mesh.nodes)
- Yield
Nodes from the mesh in order.
- Type
-
property
node_strings
¶ Iterate over the node strings in the mesh.
This is synonymous to calling
py2dm.Reader.iter_node_strings()
with default arguments.If you prefer a list of node strings instead, pass this iterator into the
list()
constructor instead:with py2dm.Reader('mesh.2dm') as mesh: nodes = list(mesh.nodes)
- Yield
Node strings from the mesh in order.
- Type
-
property
materials_per_element
¶ Number of materials per element.
This value will be set by the
NUM_MATERIALS_PER_ELEM <count>
card. Alternatively, the user may specify the number of materials to use via the materials keyword argument.If the number of materials is not specified in the file or via the materials argument, the number of elements will default to 0.
- Type
-
property
extent
¶ Return the extents of the mesh as a tuple of four floats.
The tuple is structured as
[minX, maxX, minY, maxY]
.If the given mesh is empty, the returned tuple will consist of four
nan
(not a number) values.Note
The 2DM format does not cache the mesh extents. The first time this property is accessed, all nodes are checked to find the extreme values, which can take considerable time for very large meshes (i.e. ones with millions of nodes).
Any successive calls will re-use this value.
-
close
() → None¶ Close the mesh reader.
This closes the underlying text file and discards any cached objects or metadata. The instance will become unusable after this call.
Note
This method is called automatically when using the class via the context manager.
-
open
() → None¶ Open the mesh reader.
This performs the initial metadata read and sets up the class for continued access.
When calling this function manually, be sure to call
close()
once you no longer require file access. Alternatively, you can use the context manager interface, in which case both methods will be called automatically.
-
element
(id_: int) → py2dm.Element¶ Return a mesh element by its unique ID.
-
node
(id_: int) → py2dm.Node¶ Return a mesh node by its unique ID.
-
node_string
(name: str) → py2dm.NodeString¶ Return a node string by its unique name.
This is only available if the node strings define a name. For meshes whose node strings are not named, convert
Reader.node_strings
to alist
and access the node strings by index.with py2dm.Reader('my-mesh.2dm') as mesh: node_strings = list(mesh.node_strings) node_string_two = node_strings[1]
- Parameters
name – Unique name of the node string
- Raises
KeyError – Raised if no node string of the given name exists
- Returns
The node string of the given name, if any.
- Return type
-
iter_elements
(start: int = - 1, end: int = - 1) → collections.abc.Iterator[py2dm.Element]¶ Iterator over the mesh elements.
- Parameters
- Raises
IndexError – Raised if the start ID is less than
1
, or if the end ID is less than or equal to the start ID, or if either of the IDs exceeds the number of elements in the mesh.- Yield
Mesh elements from the given range of IDs.
- Type
-
iter_nodes
(start: int = - 1, end: int = - 1) → collections.abc.Iterator[py2dm.Node]¶ Iterator over the mesh nodes.
- Parameters
- Raises
IndexError – Raised if the start ID is less than
1
, or if the end ID is less than or equal to the start ID, or if either of the IDs exceeds the number of nodes in the mesh.- Yield
Mesh nodes from the given range of IDs.
- Type
-
iter_node_strings
(start: int = 0, end: int = - 1) → collections.abc.Iterator[py2dm.NodeString]¶ Iterator over the mesh’s node strings.
Note
Unlike
Reader.iter_elements()
orReader.iter_nodes()
, this method uses Python slicing notation for its ranges due to node strings not having explicit IDs.Even if the mesh is using one-indexed IDs, starting iteration on the second node string still requires setting start to
1
when using this function.- Parameters
- Raises
IndexError – Raised if the start ID is less than
0
, or if the end ID is less than or equal to the start ID, or if either of the IDs reaches the number of node strings in the mesh.- Yield
Mesh node strings in order of definition.
- Type
-