emerge 0.4.7__py3-none-any.whl → 0.4.8__py3-none-any.whl
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 emerge might be problematic. Click here for more details.
- emerge/__init__.py +14 -14
- emerge/_emerge/__init__.py +42 -0
- emerge/_emerge/bc.py +197 -0
- emerge/_emerge/coord.py +119 -0
- emerge/_emerge/cs.py +523 -0
- emerge/_emerge/dataset.py +36 -0
- emerge/_emerge/elements/__init__.py +19 -0
- emerge/_emerge/elements/femdata.py +212 -0
- emerge/_emerge/elements/index_interp.py +64 -0
- emerge/_emerge/elements/legrange2.py +172 -0
- emerge/_emerge/elements/ned2_interp.py +645 -0
- emerge/_emerge/elements/nedelec2.py +140 -0
- emerge/_emerge/elements/nedleg2.py +217 -0
- emerge/_emerge/geo/__init__.py +24 -0
- emerge/_emerge/geo/horn.py +107 -0
- emerge/_emerge/geo/modeler.py +449 -0
- emerge/_emerge/geo/operations.py +254 -0
- emerge/_emerge/geo/pcb.py +1244 -0
- emerge/_emerge/geo/pcb_tools/calculator.py +28 -0
- emerge/_emerge/geo/pcb_tools/macro.py +79 -0
- emerge/_emerge/geo/pmlbox.py +204 -0
- emerge/_emerge/geo/polybased.py +529 -0
- emerge/_emerge/geo/shapes.py +427 -0
- emerge/_emerge/geo/step.py +77 -0
- emerge/_emerge/geo2d.py +86 -0
- emerge/_emerge/geometry.py +510 -0
- emerge/_emerge/howto.py +214 -0
- emerge/_emerge/logsettings.py +5 -0
- emerge/_emerge/material.py +118 -0
- emerge/_emerge/mesh3d.py +730 -0
- emerge/_emerge/mesher.py +339 -0
- emerge/_emerge/mth/common_functions.py +33 -0
- emerge/_emerge/mth/integrals.py +71 -0
- emerge/_emerge/mth/optimized.py +357 -0
- emerge/_emerge/periodic.py +263 -0
- emerge/_emerge/physics/__init__.py +0 -0
- emerge/_emerge/physics/microwave/__init__.py +1 -0
- emerge/_emerge/physics/microwave/adaptive_freq.py +279 -0
- emerge/_emerge/physics/microwave/assembly/assembler.py +569 -0
- emerge/_emerge/physics/microwave/assembly/curlcurl.py +448 -0
- emerge/_emerge/physics/microwave/assembly/generalized_eigen.py +426 -0
- emerge/_emerge/physics/microwave/assembly/robinbc.py +433 -0
- emerge/_emerge/physics/microwave/microwave_3d.py +1150 -0
- emerge/_emerge/physics/microwave/microwave_bc.py +915 -0
- emerge/_emerge/physics/microwave/microwave_data.py +1148 -0
- emerge/_emerge/physics/microwave/periodic.py +82 -0
- emerge/_emerge/physics/microwave/port_functions.py +53 -0
- emerge/_emerge/physics/microwave/sc.py +175 -0
- emerge/_emerge/physics/microwave/simjob.py +147 -0
- emerge/_emerge/physics/microwave/sparam.py +138 -0
- emerge/_emerge/physics/microwave/touchstone.py +140 -0
- emerge/_emerge/plot/__init__.py +0 -0
- emerge/_emerge/plot/display.py +394 -0
- emerge/_emerge/plot/grapher.py +93 -0
- emerge/_emerge/plot/matplotlib/mpldisplay.py +264 -0
- emerge/_emerge/plot/pyvista/__init__.py +1 -0
- emerge/_emerge/plot/pyvista/display.py +931 -0
- emerge/_emerge/plot/pyvista/display_settings.py +24 -0
- emerge/_emerge/plot/simple_plots.py +551 -0
- emerge/_emerge/plot.py +225 -0
- emerge/_emerge/projects/__init__.py +0 -0
- emerge/_emerge/projects/_gen_base.txt +32 -0
- emerge/_emerge/projects/_load_base.txt +24 -0
- emerge/_emerge/projects/generate_project.py +40 -0
- emerge/_emerge/selection.py +596 -0
- emerge/_emerge/simmodel.py +444 -0
- emerge/_emerge/simulation_data.py +411 -0
- emerge/_emerge/solver.py +993 -0
- emerge/_emerge/system.py +54 -0
- emerge/cli.py +19 -0
- emerge/lib.py +1 -1
- emerge/plot.py +1 -1
- {emerge-0.4.7.dist-info → emerge-0.4.8.dist-info}/METADATA +1 -1
- emerge-0.4.8.dist-info/RECORD +78 -0
- emerge-0.4.8.dist-info/entry_points.txt +2 -0
- emerge-0.4.7.dist-info/RECORD +0 -9
- emerge-0.4.7.dist-info/entry_points.txt +0 -2
- {emerge-0.4.7.dist-info → emerge-0.4.8.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# EMerge is an open source Python based FEM EM simulation module.
|
|
2
|
+
# Copyright (C) 2025 Andrés Martínez Mera.
|
|
3
|
+
# Copyright (C) 2025 Robert Fennis.
|
|
4
|
+
|
|
5
|
+
# This program is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU General Public License
|
|
7
|
+
# as published by the Free Software Foundation; either version 2
|
|
8
|
+
# of the License, or (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with this program; if not, see
|
|
17
|
+
# <https://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
import os
|
|
20
|
+
from typing import Literal
|
|
21
|
+
import numpy as np
|
|
22
|
+
from datetime import datetime
|
|
23
|
+
from loguru import logger
|
|
24
|
+
|
|
25
|
+
_F_UNIT = {'HZ': 1,
|
|
26
|
+
'KHZ': 1e3,
|
|
27
|
+
'MHZ': 1e6,
|
|
28
|
+
'GHZ': 1e9,
|
|
29
|
+
}
|
|
30
|
+
def generate_touchstone(filename: str,
|
|
31
|
+
freq: np.ndarray,
|
|
32
|
+
Smat: np.ndarray,
|
|
33
|
+
data_format: Literal['RI','MA','DB'],
|
|
34
|
+
custom_comments: list[str] = None,
|
|
35
|
+
funit: Literal['HZ','KHZ','MHZ','GHZ'] = 'GHZ') -> None:
|
|
36
|
+
"""
|
|
37
|
+
Export S-parameter data to a Touchstone file
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
filename : str
|
|
42
|
+
Base filename (may include path). If no extension is given, one
|
|
43
|
+
will be added of the form '.sNp' where N = number of ports.
|
|
44
|
+
freq : np.ndarray
|
|
45
|
+
1-D array of M frequency points, in Hz.
|
|
46
|
+
Smat : np.ndarray
|
|
47
|
+
3-D array of S-parameters with shape (M, N, N).
|
|
48
|
+
data_format : {'RI','MA','DB'}
|
|
49
|
+
RI = real&imag, MA = magnitude&angle (deg), DB = dB&angle (deg).
|
|
50
|
+
custom_comments : list[str], optional
|
|
51
|
+
List of custom comment strings to add to the touchstone file header.
|
|
52
|
+
Each string will be prefixed with "! " automatically.
|
|
53
|
+
"""
|
|
54
|
+
# --- validations ---
|
|
55
|
+
if Smat.ndim != 3:
|
|
56
|
+
raise ValueError(f"Smat must be 3-D with shape (M,N,N), got ndim={Smat.ndim}")
|
|
57
|
+
M, Nports, N2 = Smat.shape
|
|
58
|
+
if Nports != N2:
|
|
59
|
+
raise ValueError(f"Smat must be square in its last two dims, got {Nports}×{N2}")
|
|
60
|
+
if freq.ndim != 1 or freq.size != M:
|
|
61
|
+
raise ValueError(f"freq must be 1-D of length {M}, got shape {freq.shape}")
|
|
62
|
+
|
|
63
|
+
# --- determine output filename & extension ---
|
|
64
|
+
base, ext = os.path.splitext(filename)
|
|
65
|
+
if ext == '':
|
|
66
|
+
ext = f".s{Nports}p"
|
|
67
|
+
filename_out = base + ext
|
|
68
|
+
|
|
69
|
+
# --- write the Touchstone file ---
|
|
70
|
+
with open(filename_out, 'w') as f:
|
|
71
|
+
# Write header
|
|
72
|
+
f.write(f"! Generated by EMerge - {Nports}-port S-parameters\n")
|
|
73
|
+
timestamp_str = datetime.now().strftime("%Y-%m-%d %H:%M %Z")
|
|
74
|
+
f.write(f"! File generated: {timestamp_str}\n")
|
|
75
|
+
|
|
76
|
+
# Write custom comments if provided
|
|
77
|
+
if custom_comments:
|
|
78
|
+
for comment in custom_comments:
|
|
79
|
+
# Ensure comment starts with "! " if not already present
|
|
80
|
+
if not comment.startswith("! "):
|
|
81
|
+
comment = "! " + comment
|
|
82
|
+
f.write(f"{comment}\n")
|
|
83
|
+
|
|
84
|
+
f.write(f"# {funit} S {data_format.upper()} R 50\n")
|
|
85
|
+
|
|
86
|
+
# Write data
|
|
87
|
+
for i in range(M):
|
|
88
|
+
freq_ghz = freq[i] / _F_UNIT[funit] # Convert Hz to GHz
|
|
89
|
+
|
|
90
|
+
# Build all S-parameter values for this frequency
|
|
91
|
+
s_values = []
|
|
92
|
+
for row in range(Nports):
|
|
93
|
+
for col in range(Nports):
|
|
94
|
+
s_val = Smat[i, row, col]
|
|
95
|
+
|
|
96
|
+
if data_format == 'RI':
|
|
97
|
+
# Real and Imaginary
|
|
98
|
+
val1 = s_val.real
|
|
99
|
+
val2 = s_val.imag
|
|
100
|
+
elif data_format == 'MA':
|
|
101
|
+
# Magnitude and Angle (degrees)
|
|
102
|
+
val1 = np.abs(s_val)
|
|
103
|
+
val2 = np.angle(s_val) * 180.0 / np.pi
|
|
104
|
+
elif data_format == 'DB':
|
|
105
|
+
# dB and Angle (degrees)
|
|
106
|
+
val1 = 20.0 * np.log10(np.abs(s_val)) if np.abs(s_val) > 0 else -300.0
|
|
107
|
+
val2 = np.angle(s_val) * 180.0 / np.pi
|
|
108
|
+
|
|
109
|
+
s_values.extend([val1, val2])
|
|
110
|
+
|
|
111
|
+
# Write frequency and S-parameters according to touchstone format
|
|
112
|
+
if Nports == 1:
|
|
113
|
+
# s1p: freq S11_real S11_imag (3 values per line)
|
|
114
|
+
f.write(f"{freq_ghz:12.6e} {s_values[0]:12.6e} {s_values[1]:12.6e}\n")
|
|
115
|
+
|
|
116
|
+
elif Nports == 2:
|
|
117
|
+
# s2p: freq S11_r S11_i S21_r S21_i S12_r S12_i S22_r S22_i (9 values per line)
|
|
118
|
+
f.write(f"{freq_ghz:12.6e}")
|
|
119
|
+
for val in s_values:
|
|
120
|
+
f.write(f" {val:12.6e}")
|
|
121
|
+
f.write("\n")
|
|
122
|
+
|
|
123
|
+
else:
|
|
124
|
+
# s3p, s4p, etc: freq on first line, then S-parameters on subsequent lines
|
|
125
|
+
f.write(f"{freq_ghz:12.6e}")
|
|
126
|
+
|
|
127
|
+
if (Nports == 3):
|
|
128
|
+
values_per_line = 6 # 3-port S-parameter
|
|
129
|
+
else:
|
|
130
|
+
values_per_line = 8 # 4-port S-parameter pairs
|
|
131
|
+
for j in range(0, len(s_values), values_per_line):
|
|
132
|
+
f.write(" ") # Indent continuation lines
|
|
133
|
+
if (j != 0):
|
|
134
|
+
f.write(' ' * 12) # Extra indentation
|
|
135
|
+
end_idx = min(j + values_per_line, len(s_values))
|
|
136
|
+
for val in s_values[j:end_idx]:
|
|
137
|
+
f.write(f" {val:12.6e}")
|
|
138
|
+
f.write("\n")
|
|
139
|
+
|
|
140
|
+
logger.info(f"Touchstone file written to '{filename_out}'")
|
|
File without changes
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
from ..mesh3d import Mesh3D
|
|
2
|
+
from ..geometry import GeoObject
|
|
3
|
+
from ..selection import Selection
|
|
4
|
+
from ..physics.microwave.microwave_bc import PortBC
|
|
5
|
+
from typing import Iterable, Literal
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
cmap_names = Literal['bgy','bgyw','kbc','blues','bmw','bmy','kgy','gray','dimgray','fire','kb','kg','kr',
|
|
9
|
+
'bkr','bky','coolwarm','gwv','bjy','bwy','cwr','colorwheel','isolum','rainbow','fire',
|
|
10
|
+
'cet_fire','gouldian','kbgyw','cwr','CET_CBL1','CET_CBL3','CET_D1A']
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BaseDisplay:
|
|
14
|
+
|
|
15
|
+
def __init__(self, mesh: Mesh3D):
|
|
16
|
+
self._mesh: Mesh3D = mesh
|
|
17
|
+
|
|
18
|
+
def show(self):
|
|
19
|
+
raise NotImplementedError('This method is not implemented')
|
|
20
|
+
|
|
21
|
+
def add_object(self, obj: GeoObject | Selection | Iterable,*args, **kwargs):
|
|
22
|
+
""" Adds an object to the display
|
|
23
|
+
|
|
24
|
+
Keyword arguments
|
|
25
|
+
----------
|
|
26
|
+
color : ColorLike, optional
|
|
27
|
+
Use to make the entire mesh have a single solid color.
|
|
28
|
+
Either a string, RGB list, or hex color string. For example:
|
|
29
|
+
``color='white'``, ``color='w'``, ``color=[1.0, 1.0, 1.0]``, or
|
|
30
|
+
``color='#FFFFFF'``. Color will be overridden if scalars are
|
|
31
|
+
specified.
|
|
32
|
+
|
|
33
|
+
Defaults to :attr:`pyvista.global_theme.color
|
|
34
|
+
<pyvista.plotting.themes.Theme.color>`.
|
|
35
|
+
|
|
36
|
+
style : str, optional
|
|
37
|
+
Visualization style of the mesh. One of the following:
|
|
38
|
+
``style='surface'``, ``style='wireframe'``, ``style='points'``,
|
|
39
|
+
``style='points_gaussian'``. Defaults to ``'surface'``. Note that
|
|
40
|
+
``'wireframe'`` only shows a wireframe of the outer geometry.
|
|
41
|
+
``'points_gaussian'`` can be modified with the ``emissive``,
|
|
42
|
+
``render_points_as_spheres`` options.
|
|
43
|
+
|
|
44
|
+
scalars : str | numpy.ndarray, optional
|
|
45
|
+
Scalars used to "color" the mesh. Accepts a string name
|
|
46
|
+
of an array that is present on the mesh or an array equal
|
|
47
|
+
to the number of cells or the number of points in the
|
|
48
|
+
mesh. Array should be sized as a single vector. If both
|
|
49
|
+
``color`` and ``scalars`` are ``None``, then the active
|
|
50
|
+
scalars are used.
|
|
51
|
+
|
|
52
|
+
clim : sequence[float], optional
|
|
53
|
+
Two item color bar range for scalars. Defaults to minimum and
|
|
54
|
+
maximum of scalars array. Example: ``[-1, 2]``. ``rng`` is
|
|
55
|
+
also an accepted alias for this.
|
|
56
|
+
|
|
57
|
+
show_edges : bool, optional
|
|
58
|
+
Shows the edges of a mesh. Does not apply to a wireframe
|
|
59
|
+
representation.
|
|
60
|
+
|
|
61
|
+
edge_color : ColorLike, optional
|
|
62
|
+
The solid color to give the edges when ``show_edges=True``.
|
|
63
|
+
Either a string, RGB list, or hex color string.
|
|
64
|
+
|
|
65
|
+
Defaults to :attr:`pyvista.global_theme.edge_color
|
|
66
|
+
<pyvista.plotting.themes.Theme.edge_color>`.
|
|
67
|
+
|
|
68
|
+
point_size : float, optional
|
|
69
|
+
Point size of any nodes in the dataset plotted. Also
|
|
70
|
+
applicable when style='points'. Default ``5.0``.
|
|
71
|
+
|
|
72
|
+
line_width : float, optional
|
|
73
|
+
Thickness of lines. Only valid for wireframe and surface
|
|
74
|
+
representations. Default ``None``.
|
|
75
|
+
|
|
76
|
+
opacity : float | str| array_like
|
|
77
|
+
Opacity of the mesh. If a single float value is given, it
|
|
78
|
+
will be the global opacity of the mesh and uniformly
|
|
79
|
+
applied everywhere - should be between 0 and 1. A string
|
|
80
|
+
can also be specified to map the scalars range to a
|
|
81
|
+
predefined opacity transfer function (options include:
|
|
82
|
+
``'linear'``, ``'linear_r'``, ``'geom'``, ``'geom_r'``).
|
|
83
|
+
A string could also be used to map a scalars array from
|
|
84
|
+
the mesh to the opacity (must have same number of elements
|
|
85
|
+
as the ``scalars`` argument). Or you can pass a custom
|
|
86
|
+
made transfer function that is an array either
|
|
87
|
+
``n_colors`` in length or shorter.
|
|
88
|
+
|
|
89
|
+
flip_scalars : bool, default: False
|
|
90
|
+
Flip direction of cmap. Most colormaps allow ``*_r``
|
|
91
|
+
suffix to do this as well.
|
|
92
|
+
|
|
93
|
+
lighting : bool, optional
|
|
94
|
+
Enable or disable view direction lighting. Default ``False``.
|
|
95
|
+
|
|
96
|
+
n_colors : int, optional
|
|
97
|
+
Number of colors to use when displaying scalars. Defaults to 256.
|
|
98
|
+
The scalar bar will also have this many colors.
|
|
99
|
+
|
|
100
|
+
interpolate_before_map : bool, optional
|
|
101
|
+
Enabling makes for a smoother scalars display. Default is
|
|
102
|
+
``True``. When ``False``, OpenGL will interpolate the
|
|
103
|
+
mapped colors which can result is showing colors that are
|
|
104
|
+
not present in the color map.
|
|
105
|
+
|
|
106
|
+
cmap : str | list | pyvista.LookupTable, default: :attr:`pyvista.plotting.themes.Theme.cmap`
|
|
107
|
+
If a string, this is the name of the ``matplotlib`` colormap to use
|
|
108
|
+
when mapping the ``scalars``. See available Matplotlib colormaps.
|
|
109
|
+
Only applicable for when displaying ``scalars``.
|
|
110
|
+
``colormap`` is also an accepted alias
|
|
111
|
+
for this. If ``colorcet`` or ``cmocean`` are installed, their
|
|
112
|
+
colormaps can be specified by name.
|
|
113
|
+
|
|
114
|
+
You can also specify a list of colors to override an existing
|
|
115
|
+
colormap with a custom one. For example, to create a three color
|
|
116
|
+
colormap you might specify ``['green', 'red', 'blue']``.
|
|
117
|
+
|
|
118
|
+
This parameter also accepts a :class:`pyvista.LookupTable`. If this
|
|
119
|
+
is set, all parameters controlling the color map like ``n_colors``
|
|
120
|
+
will be ignored.
|
|
121
|
+
|
|
122
|
+
label : str, optional
|
|
123
|
+
String label to use when adding a legend to the scene with
|
|
124
|
+
:func:`pyvista.Plotter.add_legend`.
|
|
125
|
+
|
|
126
|
+
reset_camera : bool, optional
|
|
127
|
+
Reset the camera after adding this mesh to the scene. The default
|
|
128
|
+
setting is ``None``, where the camera is only reset if this plotter
|
|
129
|
+
has already been shown. If ``False``, the camera is not reset
|
|
130
|
+
regardless of the state of the ``Plotter``. When ``True``, the
|
|
131
|
+
camera is always reset.
|
|
132
|
+
|
|
133
|
+
scalar_bar_args : dict, optional
|
|
134
|
+
Dictionary of keyword arguments to pass when adding the
|
|
135
|
+
scalar bar to the scene. For options, see
|
|
136
|
+
:func:`pyvista.Plotter.add_scalar_bar`.
|
|
137
|
+
|
|
138
|
+
show_scalar_bar : bool, optional
|
|
139
|
+
If ``False``, a scalar bar will not be added to the
|
|
140
|
+
scene.
|
|
141
|
+
|
|
142
|
+
multi_colors : bool | str | cycler.Cycler | sequence[ColorLike], default: False
|
|
143
|
+
If a :class:`pyvista.MultiBlock` dataset is given this will color
|
|
144
|
+
each block by a solid color using a custom cycler.
|
|
145
|
+
|
|
146
|
+
If ``True``, the default 'matplotlib' color cycler is used.
|
|
147
|
+
|
|
148
|
+
See :func:`set_color_cycler<Plotter.set_color_cycler>` for usage of
|
|
149
|
+
custom color cycles.
|
|
150
|
+
|
|
151
|
+
name : str, optional
|
|
152
|
+
The name for the added mesh/actor so that it can be easily
|
|
153
|
+
updated. If an actor of this name already exists in the
|
|
154
|
+
rendering window, it will be replaced by the new actor.
|
|
155
|
+
|
|
156
|
+
texture : pyvista.Texture or np.ndarray, optional
|
|
157
|
+
A texture to apply if the input mesh has texture
|
|
158
|
+
coordinates. This will not work with MultiBlock
|
|
159
|
+
datasets.
|
|
160
|
+
|
|
161
|
+
render_points_as_spheres : bool, optional
|
|
162
|
+
Render points as spheres rather than dots.
|
|
163
|
+
|
|
164
|
+
render_lines_as_tubes : bool, optional
|
|
165
|
+
Show lines as thick tubes rather than flat lines. Control
|
|
166
|
+
the width with ``line_width``.
|
|
167
|
+
|
|
168
|
+
smooth_shading : bool, optional
|
|
169
|
+
Enable smooth shading when ``True`` using the Phong
|
|
170
|
+
shading algorithm. When ``False``, use flat shading.
|
|
171
|
+
Automatically enabled when ``pbr=True``. See
|
|
172
|
+
:ref:`shading_example`.
|
|
173
|
+
|
|
174
|
+
split_sharp_edges : bool, optional
|
|
175
|
+
Split sharp edges exceeding 30 degrees when plotting with smooth
|
|
176
|
+
shading. Control the angle with the optional keyword argument
|
|
177
|
+
``feature_angle``. By default this is ``False`` unless overridden
|
|
178
|
+
by the global or plotter theme. Note that enabling this will
|
|
179
|
+
create a copy of the input mesh within the plotter. See
|
|
180
|
+
:ref:`shading_example`.
|
|
181
|
+
|
|
182
|
+
ambient : float, optional
|
|
183
|
+
When lighting is enabled, this is the amount of light in
|
|
184
|
+
the range of 0 to 1 (default 0.0) that reaches the actor
|
|
185
|
+
when not directed at the light source emitted from the
|
|
186
|
+
viewer.
|
|
187
|
+
|
|
188
|
+
diffuse : float, optional
|
|
189
|
+
The diffuse lighting coefficient. Default 1.0.
|
|
190
|
+
|
|
191
|
+
specular : float, optional
|
|
192
|
+
The specular lighting coefficient. Default 0.0.
|
|
193
|
+
|
|
194
|
+
specular_power : float, optional
|
|
195
|
+
The specular power. Between 0.0 and 128.0.
|
|
196
|
+
|
|
197
|
+
nan_color : ColorLike, optional
|
|
198
|
+
The color to use for all ``NaN`` values in the plotted
|
|
199
|
+
scalar array.
|
|
200
|
+
|
|
201
|
+
nan_opacity : float, optional
|
|
202
|
+
Opacity of ``NaN`` values. Should be between 0 and 1.
|
|
203
|
+
Default 1.0.
|
|
204
|
+
|
|
205
|
+
culling : str, optional
|
|
206
|
+
Does not render faces that are culled. Options are
|
|
207
|
+
``'front'`` or ``'back'``. This can be helpful for dense
|
|
208
|
+
surface meshes, especially when edges are visible, but can
|
|
209
|
+
cause flat meshes to be partially displayed. Defaults to
|
|
210
|
+
``False``.
|
|
211
|
+
|
|
212
|
+
rgb : bool, optional
|
|
213
|
+
If an 2 dimensional array is passed as the scalars, plot
|
|
214
|
+
those values as RGB(A) colors. ``rgba`` is also an
|
|
215
|
+
accepted alias for this. Opacity (the A) is optional. If
|
|
216
|
+
a scalars array ending with ``"_rgba"`` is passed, the default
|
|
217
|
+
becomes ``True``. This can be overridden by setting this
|
|
218
|
+
parameter to ``False``.
|
|
219
|
+
|
|
220
|
+
categories : bool, optional
|
|
221
|
+
If set to ``True``, then the number of unique values in
|
|
222
|
+
the scalar array will be used as the ``n_colors``
|
|
223
|
+
argument.
|
|
224
|
+
|
|
225
|
+
silhouette : dict, bool, optional
|
|
226
|
+
If set to ``True``, plot a silhouette highlight for the
|
|
227
|
+
mesh. This feature is only available for a triangulated
|
|
228
|
+
``PolyData``. As a ``dict``, it contains the properties
|
|
229
|
+
of the silhouette to display:
|
|
230
|
+
|
|
231
|
+
* ``color``: ``ColorLike``, color of the silhouette
|
|
232
|
+
* ``line_width``: ``float``, edge width
|
|
233
|
+
* ``opacity``: ``float`` between 0 and 1, edge transparency
|
|
234
|
+
* ``feature_angle``: If a ``float``, display sharp edges
|
|
235
|
+
exceeding that angle in degrees.
|
|
236
|
+
* ``decimate``: ``float`` between 0 and 1, level of decimation
|
|
237
|
+
|
|
238
|
+
use_transparency : bool, optional
|
|
239
|
+
Invert the opacity mappings and make the values correspond
|
|
240
|
+
to transparency.
|
|
241
|
+
|
|
242
|
+
below_color : ColorLike, optional
|
|
243
|
+
Solid color for values below the scalars range
|
|
244
|
+
(``clim``). This will automatically set the scalar bar
|
|
245
|
+
``below_label`` to ``'below'``.
|
|
246
|
+
|
|
247
|
+
above_color : ColorLike, optional
|
|
248
|
+
Solid color for values below the scalars range
|
|
249
|
+
(``clim``). This will automatically set the scalar bar
|
|
250
|
+
``above_label`` to ``'above'``.
|
|
251
|
+
|
|
252
|
+
annotations : dict, optional
|
|
253
|
+
Pass a dictionary of annotations. Keys are the float
|
|
254
|
+
values in the scalars range to annotate on the scalar bar
|
|
255
|
+
and the values are the string annotations.
|
|
256
|
+
|
|
257
|
+
pickable : bool, optional
|
|
258
|
+
Set whether this actor is pickable.
|
|
259
|
+
|
|
260
|
+
preference : str, default: "point"
|
|
261
|
+
When ``mesh.n_points == mesh.n_cells`` and setting
|
|
262
|
+
scalars, this parameter sets how the scalars will be
|
|
263
|
+
mapped to the mesh. Default ``'point'``, causes the
|
|
264
|
+
scalars will be associated with the mesh points. Can be
|
|
265
|
+
either ``'point'`` or ``'cell'``.
|
|
266
|
+
|
|
267
|
+
log_scale : bool, default: False
|
|
268
|
+
Use log scale when mapping data to colors. Scalars less
|
|
269
|
+
than zero are mapped to the smallest representable
|
|
270
|
+
positive float.
|
|
271
|
+
|
|
272
|
+
pbr : bool, optional
|
|
273
|
+
Enable physics based rendering (PBR) if the mesh is
|
|
274
|
+
``PolyData``. Use the ``color`` argument to set the base
|
|
275
|
+
color.
|
|
276
|
+
|
|
277
|
+
metallic : float, optional
|
|
278
|
+
Usually this value is either 0 or 1 for a real material
|
|
279
|
+
but any value in between is valid. This parameter is only
|
|
280
|
+
used by PBR interpolation.
|
|
281
|
+
|
|
282
|
+
roughness : float, optional
|
|
283
|
+
This value has to be between 0 (glossy) and 1 (rough). A
|
|
284
|
+
glossy material has reflections and a high specular
|
|
285
|
+
part. This parameter is only used by PBR
|
|
286
|
+
interpolation.
|
|
287
|
+
|
|
288
|
+
render : bool, default: True
|
|
289
|
+
Force a render when ``True``.
|
|
290
|
+
|
|
291
|
+
user_matrix : np.ndarray | vtk.vtkMatrix4x4, default: np.eye(4)
|
|
292
|
+
Matrix passed to the Actor class before rendering. This affects the
|
|
293
|
+
actor/rendering only, not the input volume itself. The user matrix is the
|
|
294
|
+
last transformation applied to the actor before rendering. Defaults to the
|
|
295
|
+
identity matrix.
|
|
296
|
+
|
|
297
|
+
component : int, optional
|
|
298
|
+
Set component of vector valued scalars to plot. Must be
|
|
299
|
+
nonnegative, if supplied. If ``None``, the magnitude of
|
|
300
|
+
the vector is plotted.
|
|
301
|
+
|
|
302
|
+
emissive : bool, optional
|
|
303
|
+
Treat the points/splats as emissive light sources. Only valid for
|
|
304
|
+
``style='points_gaussian'`` representation.
|
|
305
|
+
|
|
306
|
+
copy_mesh : bool, default: False
|
|
307
|
+
If ``True``, a copy of the mesh will be made before adding it to
|
|
308
|
+
the plotter. This is useful if you would like to add the same
|
|
309
|
+
mesh to a plotter multiple times and display different
|
|
310
|
+
scalars. Setting ``copy_mesh`` to ``False`` is necessary if you
|
|
311
|
+
would like to update the mesh after adding it to the plotter and
|
|
312
|
+
have these updates rendered, e.g. by changing the active scalars or
|
|
313
|
+
through an interactive widget. This should only be set to ``True``
|
|
314
|
+
with caution. Defaults to ``False``. This is ignored if the input
|
|
315
|
+
is a ``vtkAlgorithm`` subclass.
|
|
316
|
+
|
|
317
|
+
backface_params : dict | pyvista.Property, optional
|
|
318
|
+
A :class:`pyvista.Property` or a dict of parameters to use for
|
|
319
|
+
backface rendering. This is useful for instance when the inside of
|
|
320
|
+
oriented surfaces has a different color than the outside. When a
|
|
321
|
+
:class:`pyvista.Property`, this is directly used for backface
|
|
322
|
+
rendering. When a dict, valid keys are :class:`pyvista.Property`
|
|
323
|
+
attributes, and values are corresponding values to use for the
|
|
324
|
+
given property. Omitted keys (or the default of
|
|
325
|
+
``backface_params=None``) default to the corresponding frontface
|
|
326
|
+
properties.
|
|
327
|
+
|
|
328
|
+
show_vertices : bool, optional
|
|
329
|
+
When ``style`` is not ``'points'``, render the external surface
|
|
330
|
+
vertices. The following optional keyword arguments may be used to
|
|
331
|
+
control the style of the vertices:
|
|
332
|
+
|
|
333
|
+
* ``vertex_color`` - The color of the vertices
|
|
334
|
+
* ``vertex_style`` - Change style to ``'points_gaussian'``
|
|
335
|
+
* ``vertex_opacity`` - Control the opacity of the vertices
|
|
336
|
+
|
|
337
|
+
edge_opacity : float, optional
|
|
338
|
+
Edge opacity of the mesh. A single float value that will be applied globally
|
|
339
|
+
edge opacity of the mesh and uniformly applied everywhere - should be
|
|
340
|
+
between 0 and 1.
|
|
341
|
+
|
|
342
|
+
.. note::
|
|
343
|
+
`edge_opacity` uses ``SetEdgeOpacity`` as the underlying method which
|
|
344
|
+
requires VTK version 9.3 or higher. If ``SetEdgeOpacity`` is not
|
|
345
|
+
available, `edge_opacity` is set to 1.
|
|
346
|
+
|
|
347
|
+
**kwargs : dict, optional
|
|
348
|
+
Optional keyword arguments.
|
|
349
|
+
"""
|
|
350
|
+
raise NotImplementedError('This method is not implemented')
|
|
351
|
+
|
|
352
|
+
def add_scatter(self, xs: np.ndarray, ys: np.ndarray, zs: np.ndarray):
|
|
353
|
+
raise NotImplementedError('This method is not implemented')
|
|
354
|
+
|
|
355
|
+
def add_portmode(self, port: PortBC, k0: float, Npoints: int = 10, dv=(0,0,0), XYZ=None,
|
|
356
|
+
field: Literal['E','H'] = 'E'):
|
|
357
|
+
raise NotImplementedError('This method is not implemented')
|
|
358
|
+
|
|
359
|
+
def add_quiver(self, x: np.ndarray, y: np.ndarray, z: np.ndarray,
|
|
360
|
+
dx: np.ndarray, dy: np.ndarray, dz: np.ndarray,
|
|
361
|
+
scale: float = 1,
|
|
362
|
+
scalemode: Literal['lin','log'] = 'lin'):
|
|
363
|
+
|
|
364
|
+
raise NotImplementedError('This method is not implemented')
|
|
365
|
+
|
|
366
|
+
def add_surf(self,
|
|
367
|
+
x: np.ndarray,
|
|
368
|
+
y: np.ndarray,
|
|
369
|
+
z: np.ndarray,
|
|
370
|
+
field: np.ndarray,
|
|
371
|
+
scale: Literal['lin','log','symlog'] = 'lin',
|
|
372
|
+
cmap: cmap_names = 'coolwarm',
|
|
373
|
+
clim: tuple[float, float] = None,
|
|
374
|
+
opacity: float = 1.0,
|
|
375
|
+
symmetrize: bool = True,
|
|
376
|
+
animate: bool = False,
|
|
377
|
+
**kwargs,):
|
|
378
|
+
"""Add a surface plot to the display
|
|
379
|
+
The X,Y,Z coordinates must be a 2D grid of data points. The field must be a real field with the same size.
|
|
380
|
+
|
|
381
|
+
Args:
|
|
382
|
+
x (np.ndarray): The X-grid array
|
|
383
|
+
y (np.ndarray): The Y-grid array
|
|
384
|
+
z (np.ndarray): The Z-grid array
|
|
385
|
+
field (np.ndarray): The scalar field to display
|
|
386
|
+
scale (Literal["lin","log","symlog"], optional): The colormap scaling¹. Defaults to 'lin'.
|
|
387
|
+
cmap (cmap_names, optional): The colormap. Defaults to 'coolwarm'.
|
|
388
|
+
clim (tuple[float, float], optional): Specific color limits (min, max). Defaults to None.
|
|
389
|
+
opacity (float, optional): The opacity of the surface. Defaults to 1.0.
|
|
390
|
+
symmetrize (bool, optional): Wether to force a symmetrical color limit (-A,A). Defaults to True.
|
|
391
|
+
|
|
392
|
+
(¹): lin: f(x)=x, log: f(x)=log₁₀(|x|), symlog: f(x)=sgn(x)·log₁₀(1+|x·ln(10)|)
|
|
393
|
+
"""
|
|
394
|
+
raise NotImplementedError('This method is not implemented')
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import matplotlib.pyplot as plt
|
|
3
|
+
import numpy as np
|
|
4
|
+
from typing import Any
|
|
5
|
+
from itertools import cycle
|
|
6
|
+
|
|
7
|
+
class Style:
|
|
8
|
+
|
|
9
|
+
def __init__(self):
|
|
10
|
+
self.linecolors: list = ['k']
|
|
11
|
+
self.linestyles: list[str] = ['-']
|
|
12
|
+
self.markers: list[str] = [None]
|
|
13
|
+
|
|
14
|
+
self.color_cycler = cycle(self.linecolors)
|
|
15
|
+
self.style_cycler = cycle(self.linestyles)
|
|
16
|
+
self.marker_cycle = cycle(self.markers)
|
|
17
|
+
|
|
18
|
+
def get_line_properties(self, color: str, linestyle: str, marker: str) -> dict[str, Any]:
|
|
19
|
+
if color is None:
|
|
20
|
+
color = next(self.color_cycler)
|
|
21
|
+
if linestyle is None:
|
|
22
|
+
linestyle = next(self.style_cycler)
|
|
23
|
+
if marker is None:
|
|
24
|
+
marker = next(self.marker_cycle)
|
|
25
|
+
return dict(color=color, linestyle=linestyle, marker=marker)
|
|
26
|
+
|
|
27
|
+
def dress(self, axis):
|
|
28
|
+
axis.grid(True, axis='both', color='k')
|
|
29
|
+
|
|
30
|
+
class Grapher:
|
|
31
|
+
|
|
32
|
+
def __init__(self):
|
|
33
|
+
self.axes: list = []
|
|
34
|
+
self.axes_grid: list[list] = []
|
|
35
|
+
self.fig = None
|
|
36
|
+
self.style: Style = Style()
|
|
37
|
+
self.nrows: int = 0
|
|
38
|
+
self.ncols: int = 0
|
|
39
|
+
self.current: int = 0
|
|
40
|
+
|
|
41
|
+
self.cur_axis = None
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def ax(self) -> plt.axis:
|
|
45
|
+
if self.cur_axis is None:
|
|
46
|
+
return self.axes[0]
|
|
47
|
+
return self.cur_axis
|
|
48
|
+
|
|
49
|
+
def reset(self):
|
|
50
|
+
self.cur_axis = None
|
|
51
|
+
|
|
52
|
+
def __call__(self, i: int = None, j: int = None) -> Grapher:
|
|
53
|
+
if i is None:
|
|
54
|
+
self.cur_axis = self.axes[0]
|
|
55
|
+
return self
|
|
56
|
+
if j is None and i is not None:
|
|
57
|
+
self.cur_axis = self.axes[i]
|
|
58
|
+
else:
|
|
59
|
+
self.cur_axis = self.axes[i,j]
|
|
60
|
+
return self
|
|
61
|
+
|
|
62
|
+
def new(self, rows: int = 1, cols: int = 1) -> Grapher:
|
|
63
|
+
self.fig, self.axes = plt.subplots(rows, cols)
|
|
64
|
+
if rows==1 and cols==1:
|
|
65
|
+
self.axes = [self.axes]
|
|
66
|
+
self.nrows = rows
|
|
67
|
+
self.ncols = cols
|
|
68
|
+
return self
|
|
69
|
+
|
|
70
|
+
def line(self,
|
|
71
|
+
xs: np.ndarray,
|
|
72
|
+
ys: np.ndarray,
|
|
73
|
+
color: str = None,
|
|
74
|
+
linestyle: str = None,
|
|
75
|
+
marker: str = None,
|
|
76
|
+
dB: bool = False) -> Grapher:
|
|
77
|
+
if dB:
|
|
78
|
+
ys = 20*np.log10(np.abs(ys))
|
|
79
|
+
self.ax.plot(xs, ys, **self.style.get_line_properties(color=color, linestyle=linestyle, marker=marker))
|
|
80
|
+
self.reset()
|
|
81
|
+
return self
|
|
82
|
+
|
|
83
|
+
def show(self):
|
|
84
|
+
for ax in self.axes:
|
|
85
|
+
self.style.dress(ax)
|
|
86
|
+
plt.show()
|
|
87
|
+
|
|
88
|
+
gr = Grapher().new()
|
|
89
|
+
|
|
90
|
+
xs = np.linspace(1e9, 2e9, 1001)
|
|
91
|
+
ys = np.sin(xs/1e8)
|
|
92
|
+
|
|
93
|
+
gr().line(xs, ys).show()
|