Source code for opstool.post.plot

from __future__ import annotations

from typing import Literal

import matplotlib.pyplot as plt

from .responses_data import get_element_responses, get_nodal_responses


[docs] def plot_nodal_responses( odb_tag: int | str, resp_type: Literal["disp", "vel", "accel", "reaction", "reactionIncInertia", "rayleighForces", "pressure"], resp_dof: Literal["UX", "UY", "UZ", "RX", "RY", "RZ"] | None = None, node_tags: list[int] | tuple[int, ...] | int | None = None, ax: plt.Axes | None = None, ) -> plt.Axes: """Read nodal responses data from a file. Added in opstool v1.0.25. .. important:: You can use :func:`opstool.post.get_nodal_responses_info` to get valid response types and DOFs. Parameters ---------- odb_tag: int | str Tag of output databases (ODB) to be read. resp_type: Literal["disp", "vel", "accel", "reaction", "reactionIncInertia", "rayleighForces", "pressure"] Type of response to be read. Optional: * "disp" - Displacement at the node. * "vel" - Velocity at the node. * "accel" - Acceleration at the node. * "reaction" - Reaction forces at the node. * "reactionIncInertia" - Reaction forces including inertial effects. * "rayleighForces" - Forces resulting from Rayleigh damping. * "pressure" - Pressure applied to the node. .. Note:: If the nodes include fluid pressure dof, such as those used for ``**UP`` elements, the pore pressure should be extracted using ``resp_type="vel"``, and the value is placed in the degree of freedom ``RZ``. resp_dof : Literal["UX", "UY", "UZ", "RX", "RY", "RZ"] Degree of freedom of response to be read. Optional: * "UX", "UY", "UZ" - Displacement/Velocity/Acceleration in X, Y, Z directions. * "RX", "RY", "RZ" - Rotational displacement/Velocity/Acceleration about X, Y, Z axes. If None, no selection on DOF is applied. If resp_type is "pressure", this parameter is ignored. node_tags: list[int] | tuple[int, ...] | int | None = None Node tags to be read. Such as [1, 2, 3] or numpy.array([1, 2, 3]) or 1. If None, return all nodal responses. .. Note:: If some nodes are deleted during the analysis, their response data will be filled with `numpy.nan`. ax: plt.Axes | None Matplotlib Axes object to plot on. If None, a new figure and axes will be created. Returns --------- plt.Axes Matplotlib Axes object containing the plot. """ nodal_resp = get_nodal_responses( odb_tag=odb_tag, resp_type=resp_type, node_tags=node_tags, print_info=False, lazy_load=False, ) if resp_dof != "pressure" and resp_dof is not None: nodal_resp = nodal_resp.sel(DOFs=resp_dof) node_tags = nodal_resp.coords["nodeTags"].values if ax is None: fig, ax = plt.subplots(figsize=(5, 3)) for node_tag in node_tags: data = nodal_resp.sel(nodeTags=node_tag) ax.plot(data.coords["time"].values, data.values, label=f"Node {node_tag}") ax.set_xlabel("Time") ax.set_ylabel(f"{resp_type}-{resp_dof}") ax.legend() ax.grid(True, which="both", color="gray", linestyle="--", linewidth=0.5) return ax
[docs] def plot_element_responses( odb_tag: int | str, ele_type: Literal["Frame", "FiberSection", "FiberSec", "Truss", "Link", "Shell", "Plane", "Solid", "Contact"], resp_type: str, resp_dof: str | None = None, ele_tags: list[int] | tuple[int, ...] | int | None = None, ax: plt.Axes | None = None, ) -> plt.Axes: """Plot element responses over time. Added in opstool v1.0.25. .. important:: You can use :func:`opstool.post.get_element_responses_info` to get valid response types and DOFs for each element type. Parameters ---------- odb_tag : int | str ODB tag to read data from. ele_type : Literal["Frame", "FiberSection", "FiberSec", "Truss", "Link", "Shell", "Plane", "Solid", "Contact"] Element type to read data from. resp_type : str Response type to read data from. This should be one of the valid response types for the specified element type. resp_dof : str | None, optional Response degree of freedom to read data from. This should be one of the valid degrees of freedom for the specified response type. If None, no selection on DOF is applied. ele_tags : list[int] | tuple[int, ...] | int | None, optional Element tags to read data from, by default None ax : plt.Axes | None, optional Matplotlib Axes object to plot on, by default None Returns ------- plt.Axes _description_ """ ele_resp = get_element_responses( odb_tag=odb_tag, ele_type=ele_type, resp_type=resp_type, ele_tags=ele_tags, print_info=False, lazy_load=False, ) if resp_dof is not None: dim = ele_resp.dims[-1] ele_resp = ele_resp.sel({dim: resp_dof}) ele_tags = ele_resp.coords["eleTags"].values if ax is None: fig, ax = plt.subplots(figsize=(5, 3)) for ele_tag in ele_tags: data = ele_resp.sel(eleTags=ele_tag) ax.plot(data.coords["time"].values, data.values, label=f"Element {ele_tag}") ax.set_xlabel("Time") ax.set_ylabel(f"{resp_type}-{resp_dof}") ax.legend() ax.grid(True, which="both", color="gray", linestyle="--", linewidth=0.5) return ax