From 5504b12f7d5fc8a471ccaa95cf7d88ffbb2128c7 Mon Sep 17 00:00:00 2001 From: maxbalrog Date: Mon, 10 Aug 2026 12:15:44 +0200 Subject: [PATCH 1/5] fix SpectralField get_a12 method calling signature --- src/quvac/field/abc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quvac/field/abc.py b/src/quvac/field/abc.py index 73c49f7..9ceed08 100644 --- a/src/quvac/field/abc.py +++ b/src/quvac/field/abc.py @@ -387,7 +387,7 @@ def _check_energy_kspace(self): ) _logger.info(f' Energy after "correction": {W_corrected:.3f} J') - def get_a12(self, t0=None): + def get_a12(self, t0=None, fft_executor=None): """ Calculates the a1 and a2 coefficients at a given time step. From 54ee0bf1ccb47560b79d2688db550aafefe9f156 Mon Sep 17 00:00:00 2001 From: maxbalrog Date: Mon, 10 Aug 2026 13:50:07 +0200 Subject: [PATCH 2/5] add transformation to the cylindrical grid --- src/quvac/postprocess.py | 85 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/quvac/postprocess.py b/src/quvac/postprocess.py index 9695f39..a22fa69 100644 --- a/src/quvac/postprocess.py +++ b/src/quvac/postprocess.py @@ -83,6 +83,30 @@ def sph2cart(r, theta, phi): return x, y, z +def cyl2cart(r, phi, z): + """ + Convert cylindrical coordinates to Cartesian coordinates. + + Parameters + ---------- + r : numpy.ndarray + Radial distance. + phi : numpy.ndarray + Azimuthal angle. + z : numpy.ndarray + Radial distance. + + Returns + ------- + x, y, z : numpy.ndarray + Cartesian coordinates. + """ + x = r * np.cos(phi) + y = r * np.sin(phi) + z = z + return x, y, z + + def xyz2idx(xyz, xyz_grid): """ Convert Cartesian coordinates to array indices. @@ -168,6 +192,67 @@ def cartesian_to_spherical_array( return spherical_grid, arr_sph +def cartesian_to_cylindrical_array( + arr, xyz_grid, cylindrical_grid=None, angular_resolution=None, + angular_resolution_factor=None, +): + """ + Transform an array with data on Cartesian grid to the array with data + on cylindrical grid. + + Parameters + ---------- + arr : numpy.ndarray + Array with data on Cartesian grid. + xyz_grid : quvac.grid.GridXYZ + Cartesian grid object. + cylindrical_grid : tuple or str, optional + Cylindrical grid or path to the file containing the cylindrical grid, + by default None. + angular_resolution : float, optional + Angular resolution, by default None. + angular_resolution_factor : float, optional + Factor that multiplies default angular resolution given by dk / kmax. + + Returns + ------- + cylindrical_grid : tuple + Spherical grid. + arr_cyl : numpy.ndarray + Array with data on cylindrical grid. + """ + # Calculate cylindrical grid if not given + if not cylindrical_grid: + dk = np.min(xyz_grid.dkxkykz[:2]) + kmax = np.max(xyz_grid.kabs) + # without the prefactor it results in too high default resolution + if angular_resolution_factor is None: + angular_resolution_factor = 3 + default_resolution = angular_resolution_factor * dk / kmax + dangle = angular_resolution if angular_resolution else default_resolution + + k = np.arange(0.0, kmax, dk, dtype=config.FDTYPE) + phi = np.arange(0.0, 2 * pi, dangle, dtype=config.FDTYPE) + kz = xyz_grid.kgrid_shifted[-1] + cylindrical_grid = (k, phi, kz) + elif isinstance(cylindrical_grid, str) and os.path.isfile(cylindrical_grid): + data = np.load(cylindrical_grid) + cylindrical_grid = (data["k"], data["phi"], data["kz"]) + cylindrical_mesh = np.meshgrid(*cylindrical_grid, indexing="ij", sparse=True) + + # Find corresponding cartesian coordinates of cylindrical mesh: + # (r,phi,z) -> (x, y, z) + xyz_for_cyl = cyl2cart(*cylindrical_mesh) + + # Convert cartesian coordinates to array idx + idxs = xyz2idx(xyz_for_cyl, xyz_grid.kgrid_shifted) + + # Interpolate data on a desired grid + # interpolation_kwargs should be implemented here + arr_cyl = map_coordinates(arr, idxs, order=1) + return cylindrical_grid, arr_cyl + + def integrate_spherical(arr, axs, axs_names=("k", "theta", "phi"), axs_integrate=("k", "theta", "phi")): """ From fea45df763f9dc047eacccf2b243683f20848555 Mon Sep 17 00:00:00 2001 From: maxbalrog Date: Mon, 10 Aug 2026 14:02:28 +0200 Subject: [PATCH 3/5] correct the dimentions in cylindrical transform --- src/quvac/postprocess.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/quvac/postprocess.py b/src/quvac/postprocess.py index a22fa69..e22ffd0 100644 --- a/src/quvac/postprocess.py +++ b/src/quvac/postprocess.py @@ -83,7 +83,7 @@ def sph2cart(r, theta, phi): return x, y, z -def cyl2cart(r, phi, z): +def cyl2cart(r, phi, zcyl): """ Convert cylindrical coordinates to Cartesian coordinates. @@ -101,9 +101,9 @@ def cyl2cart(r, phi, z): x, y, z : numpy.ndarray Cartesian coordinates. """ - x = r * np.cos(phi) - y = r * np.sin(phi) - z = z + x = r * np.cos(phi) * np.ones_like(zcyl) + y = r * np.sin(phi) * np.ones_like(zcyl) + z = zcyl * np.ones_like(r) * np.ones_like(phi) return x, y, z @@ -217,7 +217,7 @@ def cartesian_to_cylindrical_array( Returns ------- cylindrical_grid : tuple - Spherical grid. + Cylindrical grid. arr_cyl : numpy.ndarray Array with data on cylindrical grid. """ From f2d69562b618be9b13ebd451d3a5328e7d215158 Mon Sep 17 00:00:00 2001 From: maxbalrog Date: Mon, 10 Aug 2026 19:24:39 +0200 Subject: [PATCH 4/5] add new optimization objective: discernible signal in spectral band --- src/quvac/cluster/optimization.py | 14 ++++++++++++- src/quvac/postprocess.py | 33 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/quvac/cluster/optimization.py b/src/quvac/cluster/optimization.py index 2ad2220..883f126 100755 --- a/src/quvac/cluster/optimization.py +++ b/src/quvac/cluster/optimization.py @@ -40,7 +40,11 @@ from quvac.log import log_time from quvac.parallel import setup_job_executor_from_params -from quvac.postprocess import integrate_spherical, signal_in_detector +from quvac.postprocess import ( + get_discernible_signal_in_frequency_band, + integrate_spherical, + signal_in_detector, +) from quvac.simulation import create_basic_logger, get_dirs, parse_args, quvac_simulation from quvac.utils import read_yaml, round_to_n, write_yaml @@ -201,6 +205,14 @@ def collect_metrics(data, obj_params, metric_names=("N_total"), metrics["N_detector"] = float(N_detector) metrics["N_detector_disc"] = float(N_detector_disc) + if "spectral_band" in obj_params: + freq_band = obj_params.get("spectral_band", (1.5,2.5)) + lam0 = obj_params.get("lam0", 800e-9) + Nband = get_discernible_signal_in_frequency_band( + data, lam0=lam0, freq_band=freq_band + ) + metrics["N_disc_band"] = Nband + # filter metrics if noiseless_observations: metrics = {k:(v,0.0) for k,v in metrics.items() if k in metric_names} diff --git a/src/quvac/postprocess.py b/src/quvac/postprocess.py index e22ffd0..0afd2e4 100644 --- a/src/quvac/postprocess.py +++ b/src/quvac/postprocess.py @@ -310,6 +310,39 @@ def integrate_spherical(arr, axs, axs_names=("k", "theta", "phi"), return integrand +def get_discernible_signal_in_frequency_band( + data, lam0=800e-9, freq_band=(1.5,2.5) +): + """ + Given a frequency band (for spectrum in spherical coordinates), + calculate the discernible signal there. + + Parameters + ---------- + data : result of np.load(...) + Simulation results. + lam0 : float + Fundamental wavelength, by default 800e-9. + freq_band : tuple + Frequency band in normalized values (by k0), by default (1.5, 2.5). + + Returns + ------- + Ndisc : float + Discernible signal. + """ + k, theta, phi, discernible_mask, signal = [ + data[key] for key in "k theta phi discernible N_sph".split() + ] + signal_discernible = signal * discernible_mask + + k0 = 2*np.pi/lam0 + idx_k = (k/k0 >= freq_band[0]) * (k/k0 <= freq_band[1]) + k_filter, signal_filter = k[idx_k], signal_discernible[idx_k] + Ndisc = integrate_spherical(signal_filter, (k_filter,theta,phi)) + return Ndisc + + def _get_detector_idx(phi, theta, phi0, theta0, dphi, dtheta): # consider detector regions that lie on the line phi=0 or phi=2*pi if phi0-dphi < 0: From afde6242682507cf4e7bcad597b8f60ddd233599 Mon Sep 17 00:00:00 2001 From: maxbalrog Date: Mon, 31 Aug 2026 12:58:05 +0200 Subject: [PATCH 5/5] update version --- src/quvac/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quvac/__init__.py b/src/quvac/__init__.py index 0058b93..bb35ee1 100644 --- a/src/quvac/__init__.py +++ b/src/quvac/__init__.py @@ -1 +1 @@ -__version__ = "1.0.1" \ No newline at end of file +__version__ = "1.0.2" \ No newline at end of file