emsutil 0.2.0__tar.gz → 0.2.2__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.
Files changed (31) hide show
  1. {emsutil-0.2.0 → emsutil-0.2.2}/.bumpversion.toml +1 -1
  2. {emsutil-0.2.0 → emsutil-0.2.2}/PKG-INFO +1 -1
  3. {emsutil-0.2.0 → emsutil-0.2.2}/pyproject.toml +1 -1
  4. emsutil-0.2.2/src/emsutil/inexport/ffdata.py +58 -0
  5. emsutil-0.2.2/src/emsutil/inexport/strutil.py +22 -0
  6. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/pyvista/display.py +87 -1
  7. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/pyvista/display_settings.py +8 -5
  8. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/themes.py +1 -1
  9. {emsutil-0.2.0 → emsutil-0.2.2}/uv.lock +1 -1
  10. {emsutil-0.2.0 → emsutil-0.2.2}/.gitignore +0 -0
  11. {emsutil-0.2.0 → emsutil-0.2.2}/.python-version +0 -0
  12. {emsutil-0.2.0 → emsutil-0.2.2}/README.md +0 -0
  13. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/__init__.py +0 -0
  14. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/const.py +0 -0
  15. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/emdata.py +0 -0
  16. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/isola.py +0 -0
  17. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/lib.py +0 -0
  18. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/material.py +0 -0
  19. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/plot/__init__.py +0 -0
  20. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/plot/plot2d.py +0 -0
  21. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/pyvista/__init__.py +0 -0
  22. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/pyvista/cmap_maker.py +0 -0
  23. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/pyvista/textures/background.png +0 -0
  24. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/pyvista/textures/tex1.png +0 -0
  25. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/pyvista/textures/tex2.png +0 -0
  26. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/pyvista/textures/tex3.png +0 -0
  27. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/pyvista/textures/tex4.png +0 -0
  28. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/pyvista/textures/tex5.png +0 -0
  29. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/pyvista/textures/tex6.png +0 -0
  30. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/pyvista/utils.py +0 -0
  31. {emsutil-0.2.0 → emsutil-0.2.2}/src/emsutil/rogers.py +0 -0
@@ -1,5 +1,5 @@
1
1
  [tool.bumpversion]
2
- current_version = "0.2.0"
2
+ current_version = "0.2.2"
3
3
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
4
4
  serialize = ["{major}.{minor}.{patch}"]
5
5
  search = "{current_version}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: emsutil
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Common utilities for Emerge projects EMerge, Optycal and Heavi
5
5
  Project-URL: Homepage, https://github.com/FennisRobert/emsutil
6
6
  Project-URL: Issues, https://github.com/FennisRobert/emsutil/issues
@@ -4,7 +4,7 @@ allow-direct-references = true
4
4
 
5
5
  [project]
6
6
  name = "emsutil"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "Common utilities for Emerge projects EMerge, Optycal and Heavi"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -0,0 +1,58 @@
1
+ import numpy as np
2
+ from .strutil import arry_to_line, matrix_to_lines, arry_to_fwl
3
+ from ..emdata import EHFieldFF
4
+
5
+ def export_ffdata(filename: str,
6
+ thetas: np.ndarray,
7
+ phis: np.ndarray,
8
+ frequencies: np.ndarray,
9
+ fields: list[EHFieldFF],
10
+ precision: int = 4) -> None:
11
+
12
+ lines = []
13
+ lines.append('% Theta (deg)')
14
+ lines.append(arry_to_line(thetas, precision=precision))
15
+ lines.append('% Phi (deg)')
16
+ lines.append(arry_to_line(phis, precision=precision))
17
+ lines.append('')
18
+ nF = frequencies.shape[0]
19
+
20
+ actual_frequencies = []
21
+ blocks = []
22
+
23
+ T, P = np.meshgrid(thetas, phis, indexing='ij')
24
+
25
+ thetal = T.flatten()
26
+ phil = P.flatten()
27
+
28
+ for iF in range(nF):
29
+ freq = frequencies[iF]
30
+ actual_frequencies.append(freq)
31
+
32
+ farfield = fields[iF]._E
33
+ Fx = farfield[0,:,:].squeeze().flatten()
34
+ Fy = farfield[1,:,:].squeeze().flatten()
35
+ Fz = farfield[2,:,:].squeeze().flatten()
36
+
37
+ block_lines = []
38
+
39
+ block_lines.append(f'# {freq} (Hz)')
40
+ block_lines.append('$ Theta(deg); Phi(deg); E_x[re](V/m); E_x[im](V/m); E_y[re](V/m); E_y[im](V/m); E_z[re](V/m); E_z[im](V/m)')
41
+ positions = (0, 14, 24, 38, 52, 66, 80, 94)
42
+ for th, ph, ex, ey, ez in zip(thetal, phil, Fx, Fy, Fz):
43
+ re_ex = np.real(ex)
44
+ im_ex = np.imag(ex)
45
+ re_ey = np.real(ey)
46
+ im_ey = np.imag(ey)
47
+ re_ez = np.real(ez)
48
+ im_ez = np.imag(ez)
49
+ line_values = np.array([th, ph, re_ex, im_ex, re_ey, im_ey, re_ez, im_ez])
50
+ line = arry_to_fwl(line_values, positions, precision=precision)
51
+ block_lines.append(line)
52
+
53
+ lines.extend(block_lines)
54
+ lines.extend('')
55
+
56
+ text = '\n'.join(lines)
57
+ with open(filename, 'w') as f:
58
+ f.write(text)
@@ -0,0 +1,22 @@
1
+ import numpy as np
2
+
3
+ def arry_to_line(array: np.ndarray, separator: str = ' ', precision: int = 4) -> str:
4
+ return separator.join([f"{x:.{precision}f}" for x in array.squeeze()])
5
+
6
+ def arry_to_fwl(array: np.ndarray, start_positions: list[int], precision: int = 4) -> str:
7
+ # Place the numbers at the starting position indices provided by the start-positions list
8
+ line_length = max(start_positions) + 10 # Extra space for number
9
+ line = [' ']*line_length
10
+ for i, pos in enumerate(start_positions):
11
+ num_str = f"{array[i]:.{precision}f}"
12
+ for j, ch in enumerate(num_str):
13
+ if pos + j < line_length:
14
+ line[pos + j] = ch
15
+ return ''.join(line)
16
+
17
+ def matrix_to_lines(matrix: np.ndarray, separator: str = ',', precision: int = 4) -> str:
18
+ lines = []
19
+ for row in matrix:
20
+ line = arry_to_line(row, separator, precision)
21
+ lines.append(line)
22
+ return '\n'.join(lines)
@@ -202,6 +202,7 @@ class EMergeDisplay:
202
202
  self._isometric: bool = False
203
203
  self._bwdrawing: bool = False
204
204
 
205
+ self._bounds: tuple[float, float, float, float, float, float] | None = None
205
206
  self._cbar_args: dict = {}
206
207
  self._cbar_lim: tuple[float, float] | None = None
207
208
  self.camera_position = (1, -1, 1) # +X, +Z, -Y
@@ -412,6 +413,23 @@ class EMergeDisplay:
412
413
  # Turn off directional lighting
413
414
  self._plot.remove_all_lights()
414
415
 
416
+ if self.set.theme.draw_pvgrid and not self._bwdrawing:
417
+ pv.set_plot_theme('dark')
418
+ bounds = self._bounds
419
+ extra_factor = 0.1
420
+ dx = (bounds[1] - bounds[0])*extra_factor
421
+ dy = (bounds[3] - bounds[2])*extra_factor
422
+ dz = (bounds[5] - bounds[4])*extra_factor
423
+ ds = max(dx, dy, dz)
424
+ bounds = (bounds[0]-ds, bounds[1]+ds, bounds[2]-ds, bounds[3]+ds, bounds[4]-ds, bounds[5]+ds)
425
+ pv.global_theme.font.fmt = "%.3f"
426
+ actor = self._plot.show_grid(
427
+ bounds=bounds,
428
+ color=self.set.theme.text_color,
429
+ fmt="%.3f",
430
+
431
+ )
432
+
415
433
  pv.global_theme.font.color = self.set.theme.text_color
416
434
  pv.global_theme.colorbar_horizontal.width = 0.4
417
435
  pv.global_theme.colorbar_vertical.height = 0.15
@@ -421,6 +439,10 @@ class EMergeDisplay:
421
439
  else:
422
440
  self._plot.disable_anti_aliasing()
423
441
  self._plot.title = 'EMerge'
442
+ if self._bwdrawing:
443
+ self._plot.set_background('white', top='white') # type: ignore
444
+ else:
445
+ self._plot.set_background(self.set.theme.backgroung_grad_1, top=self.set.theme.backgroung_grad_2) # type: ignore
424
446
 
425
447
  def _reset(self):
426
448
  self._plot.close()
@@ -985,6 +1007,68 @@ class EMergeDisplay:
985
1007
  pl = self._plot.add_arrows(Coo, Vec, scalars=None, clim=None, cmap=cmap, **kwargs)
986
1008
  self._data_sets.append(pl.mapper.dataset)
987
1009
  self._reset_cbar()
1010
+
1011
+ def add_clip_volume(self,
1012
+ X: np.ndarray,
1013
+ Y: np.ndarray,
1014
+ Z: np.ndarray,
1015
+ V: np.ndarray,
1016
+ scale: Literal['lin','log','symlog'] = 'lin',
1017
+ symmetrize: bool = False,
1018
+ clim: tuple[float, float] | None = None,
1019
+ cmap: cmap_names | None = None,
1020
+ opacity: float = 0.8):
1021
+ """Adds a 3D volumetric contourplot based on a 3D grid of X,Y,Z and field values
1022
+
1023
+ Args:
1024
+ X (np.ndarray): A 3D Grid of X-values
1025
+ Y (np.ndarray): A 3D Grid of Y-values
1026
+ Z (np.ndarray): A 3D Grid of Z-values
1027
+ V (np.ndarray): The scalar quantity to plot ()
1028
+ Nlevels (int, optional): The number of contour levels. Defaults to 5.
1029
+ symmetrize (bool, optional): Wether to symmetrize the countour levels (-V,V). Defaults to True.
1030
+ cmap (str, optional): The color map. Defaults to 'viridis'.
1031
+ """
1032
+ Vf = V.flatten()
1033
+ Vf = np.nan_to_num(Vf)
1034
+ vmin = np.min(np.real(Vf))
1035
+ vmax = np.max(np.real(Vf))
1036
+
1037
+ default_cmap = self.set.theme.default_amplitude_cmap
1038
+
1039
+ if scale=='log':
1040
+ T = lambda x: np.log10(np.abs(x+1e-12))
1041
+ elif scale=='symlog':
1042
+ T = lambda x: np.sign(x) * np.log10(1 + np.abs(x*np.log(10)))
1043
+ else:
1044
+ T = lambda x: x
1045
+
1046
+ if symmetrize:
1047
+ level = np.max(np.abs(Vf))
1048
+ vmin, vmax = (-level, level)
1049
+ default_cmap = self.set.theme.default_wave_cmap
1050
+
1051
+ if clim is None:
1052
+ if self._cbar_lim is not None:
1053
+ clim = self._cbar_lim
1054
+ vmin, vmax = clim
1055
+ else:
1056
+ clim = (vmin, vmax)
1057
+
1058
+ if cmap is None:
1059
+ cmap = default_cmap
1060
+ else:
1061
+ cmap = self.set.theme.parse_cmap_name(cmap)
1062
+
1063
+ grid = pv.StructuredGrid(X,Y,Z)
1064
+ field = V.flatten(order='F')
1065
+ grid['anim'] = T(np.real(field))
1066
+
1067
+
1068
+ self._plot.add_mesh_clip_plane(grid, opacity=opacity, cmap=cmap, pickable=False, scalar_bar_args=self._cbar_args)
1069
+ #actor = self._wrap_plot(contour, opacity=opacity, cmap=cmap, clim=clim, pickable=False, scalar_bar_args=self._cbar_args)
1070
+
1071
+ self._reset_cbar()
988
1072
 
989
1073
  def add_contour(self,
990
1074
  X: np.ndarray,
@@ -1082,6 +1166,8 @@ class EMergeDisplay:
1082
1166
 
1083
1167
  #self._plot.add_logo_widget('src/_img/logo.jpeg',position=(0.89,0.89), size=(0.1,0.1))
1084
1168
  bounds = self._plot.bounds
1169
+ self._bounds = bounds
1170
+
1085
1171
  xmin, xmax, ymin, ymax, zmin, zmax = self._plot.bounds
1086
1172
 
1087
1173
  max_size = max([abs(dim) for dim in [bounds.x_max, bounds.x_min, bounds.y_max, bounds.y_min, bounds.z_max, bounds.z_min]])
@@ -1287,7 +1373,7 @@ class EMergeDisplay:
1287
1373
  light.set_direction_angle(*self.set.light_angle) # type: ignore
1288
1374
  self._plot.add_light(light)
1289
1375
 
1290
- self._plot.set_background(self.set.theme.backgroung_grad_1, top=self.set.theme.backgroung_grad_2) # type: ignore
1376
+
1291
1377
  self._plot.add_axes(color=self.set.theme.text_color,
1292
1378
  x_color=col_x,
1293
1379
  y_color=col_y,
@@ -29,9 +29,10 @@ class EMergeTheme:
29
29
 
30
30
  def __init__(self):
31
31
 
32
+
32
33
  # Generic Controls
33
34
  self.aa_active: bool = True
34
- self.aa_mode: str = "msaa"
35
+ self.aa_mode: Literal['msaa', 'fxaa', 'ssaa'] = "msaa"
35
36
  self.aa_samples: int = 8
36
37
 
37
38
  # Background
@@ -44,10 +45,12 @@ class EMergeTheme:
44
45
  self.draw_zplane: bool = False
45
46
  self.draw_xgrid: bool = False
46
47
  self.draw_ygrid: bool = False
47
- self.draw_zgrid: bool = True
48
- self.draw_xax: bool = True
49
- self.draw_yax: bool = True
50
- self.draw_zax: bool = True
48
+ self.draw_zgrid: bool = False
49
+ self.draw_xax: bool = False
50
+ self.draw_yax: bool = False
51
+ self.draw_zax: bool = False
52
+ self.draw_pvgrid: bool = True
53
+ self.draw_pvaxes: bool = True
51
54
 
52
55
  self.axis_color: str = "#000000"
53
56
  self.axis_x_color: str = "#ff007b"
@@ -106,7 +106,7 @@ class _Tron(EMergeTheme):
106
106
  self.axis_x_color = "#FFFF00FF"
107
107
  self.axis_y_color = "#00FFFFFF"
108
108
  self.axis_z_color = "#FF00FFFF"
109
-
109
+ self.draw_pvaxes = True
110
110
  self.aa_active = True
111
111
  self.aa_samples = 5
112
112
  self.cmap_npts = 32
@@ -279,7 +279,7 @@ wheels = [
279
279
 
280
280
  [[package]]
281
281
  name = "emsutil"
282
- version = "0.2.0"
282
+ version = "0.2.2"
283
283
  source = { editable = "." }
284
284
  dependencies = [
285
285
  { name = "loguru" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes