|
| 1 | +"""Module containing the helpers for streamlines. |
| 2 | +
|
| 3 | +Streamlines |
| 4 | +----------- |
| 5 | +
|
| 6 | +""" |
| 7 | +from typing import List, Union |
| 8 | + |
| 9 | +from ansys.dpf.core.helpers import streamlines as core_streamlines |
| 10 | +from ansys.dpf.core.plotter import DpfPlotter |
| 11 | + |
| 12 | +from ansys.dpf import core as dpf |
| 13 | +from ansys.dpf import post |
| 14 | + |
| 15 | + |
| 16 | +def plot_streamlines( |
| 17 | + dataframe: post.DataFrame, |
| 18 | + sources: List[dict], |
| 19 | + set_id: int = 1, |
| 20 | + streamline_thickness: Union[float, List[float]] = 0.01, |
| 21 | + plot_mesh: bool = True, |
| 22 | + mesh_opacity: float = 0.3, |
| 23 | + plot_contour: bool = True, |
| 24 | + contour_opacity: float = 0.3, |
| 25 | + **kwargs, |
| 26 | +): |
| 27 | + """Plot streamlines based on a vector field DataFrame. |
| 28 | +
|
| 29 | + Parameters |
| 30 | + ---------- |
| 31 | + dataframe: |
| 32 | + A `post.DataFrame` object containing a vector field. |
| 33 | + If present, merges the `DataFrame` across its `zone` label before plotting. |
| 34 | + sources: |
| 35 | + A list of dictionaries defining spherical point sources for the streamlines. |
| 36 | + Expected keywords are "center", "radius", "max_time" and "n_points". |
| 37 | + Keyword "max_time" is for the maximum integration pseudo-time for the streamline |
| 38 | + computation algorithm, which defines the final length of the lines. |
| 39 | + More information is available at :func:`pyvista.DataSetFilters.streamlines`. |
| 40 | + set_id: |
| 41 | + ID of the set (time-step) for which to compute streamlines if the `DataFrame` object |
| 42 | + contains temporal data. |
| 43 | + streamline_thickness: |
| 44 | + Thickness of the streamlines plotted. Use a list to specify a value for each source. |
| 45 | + plot_contour: |
| 46 | + Whether to plot the field's norm contour along with the streamlines. |
| 47 | + contour_opacity: |
| 48 | + Opacity to use for the field contour in case "plot_contour=True". |
| 49 | + plot_mesh: |
| 50 | + Whether to plot the mesh along the streamlines in case "plot_contour=False". |
| 51 | + mesh_opacity: |
| 52 | + Opacity to use for the mesh in case "plot_contour=False" and "plot_mesh=True". |
| 53 | + **kwargs: |
| 54 | +
|
| 55 | + """ |
| 56 | + # Select data to work with |
| 57 | + fc = dataframe._fc |
| 58 | + if "zone" in dataframe.columns.names: |
| 59 | + fc = dpf.operators.utility.merge_fields_by_label( |
| 60 | + fields_container=fc, |
| 61 | + label="zone", |
| 62 | + ).outputs.fields_container() |
| 63 | + if set_id not in dataframe.columns.set_index.values: |
| 64 | + raise ValueError("The set_id requested is not available in this dataframe.") |
| 65 | + field = fc.get_field_by_time_id(timeid=set_id) |
| 66 | + meshed_region = field.meshed_region |
| 67 | + |
| 68 | + # Initialize the plotter |
| 69 | + plt = DpfPlotter(**kwargs) |
| 70 | + |
| 71 | + if plot_contour: |
| 72 | + plt.add_field(field=field, opacity=contour_opacity) |
| 73 | + elif plot_mesh: |
| 74 | + plt.add_mesh(meshed_region=meshed_region, opacity=mesh_opacity) |
| 75 | + if not isinstance(streamline_thickness, list): |
| 76 | + streamline_thickness = [streamline_thickness] * len(sources) |
| 77 | + # Add streamlines for each source |
| 78 | + for i, source in enumerate(sources): |
| 79 | + pv_streamline, pv_source = core_streamlines.compute_streamlines( |
| 80 | + meshed_region=meshed_region, |
| 81 | + field=field, |
| 82 | + return_source=True, |
| 83 | + source_radius=source["radius"], |
| 84 | + source_center=source["center"], |
| 85 | + n_points=source["n_points"] if "n_points" in source else 100, |
| 86 | + max_time=source["max_time"] if "max_time" in source else None, |
| 87 | + ) |
| 88 | + plt.add_streamlines( |
| 89 | + pv_streamline, source=pv_source, radius=streamline_thickness[i] |
| 90 | + ) |
| 91 | + |
| 92 | + plt.show_figure(**kwargs) |
0 commit comments