Commit 8331847f by Martin Reinecke

### introduce PowerProjectionOperator

parent 09c9b645
Pipeline #19441 failed with stage
in 3 minutes and 59 seconds
 ... ... @@ -28,6 +28,11 @@ class DomainTuple(object): shape_tuple = tuple(sp.shape for sp in self._dom) self._shape = reduce(lambda x, y: x + y, shape_tuple, ()) self._dim = reduce(lambda x, y: x * y, self._shape, 1) self._accdims = (1,) prod = 1 for dom in self._dom: prod *= dom.dim self._accdims += (prod,) def _get_axes_tuple(self): i = 0 ... ... @@ -110,3 +115,14 @@ class DomainTuple(object): for i in self.domains: res += "\n" + str(i) return res def collapsed_shape_for_domain(self, ispace): """Returns a three-component shape, with the total number of pixels in the domains before the requested space in res[0], the total number of pixels in the requested space in res[1], and the remaining pixels in res[2]. """ dims = (dom.dim for dom in self._dom) return (self._accdims[ispace], self._accdims[ispace+1]/self._accdims[ispace], self._accdims[-1]/self._accdims[ispace+1])
 ... ... @@ -26,7 +26,6 @@ from .domain_tuple import DomainTuple from functools import reduce from . import dobj class Field(object): """ The discrete representation of a continuous field over multiple spaces. ... ... @@ -219,27 +218,19 @@ class Field(object): idx=space_index, binbounds=binbounds) for part in parts] parts = [ part.weight(-1,spaces) for part in parts ] return parts[0] + 1j*parts[1] if keep_phase_information else parts[0] @staticmethod def _single_power_analyze(field, idx, binbounds): from .operators.power_projection_operator import PowerProjectionOperator power_domain = PowerSpace(field.domain[idx], binbounds) pindex = power_domain.pindex axes = field.domain.axes[idx] new_pindex_shape = [1] * len(field.shape) for i, ax in enumerate(axes): new_pindex_shape[ax] = pindex.shape[i] pindex = np.broadcast_to(pindex.reshape(new_pindex_shape), field.shape) power_spectrum = dobj.bincount_axis(pindex, weights=field.val, axis=axes) result_domain = list(field.domain) result_domain[idx] = power_domain return Field(result_domain, power_spectrum) ppo = PowerProjectionOperator(field.domain,idx,power_domain) return ppo(field) def _compute_spec(self, spaces): from .operators.power_projection_operator import PowerProjectionOperator from .basic_arithmetics import sqrt if spaces is None: spaces = range(len(self.domain)) else: ... ... @@ -247,23 +238,14 @@ class Field(object): # create the result domain result_domain = list(self.domain) spec = sqrt(self) for i in spaces: if not isinstance(self.domain[i], PowerSpace): raise ValueError("A PowerSpace is needed for field " "synthetization.") result_domain[i] = self.domain[i].harmonic_partner ppo = PowerProjectionOperator(result_domain,i,self.domain[i]) spec = ppo.adjoint_times(spec) spec = dobj.sqrt(self.val) for i in spaces: power_space = self.domain[i] local_blow_up = [slice(None)]*len(spec.shape) # it is important to count from behind, since spec potentially # grows with every iteration index = self.domain.axes[i][0]-len(self.shape) local_blow_up[index] = power_space.pindex # here, the power_spectrum is distributed into the new shape spec = spec[local_blow_up] return Field(result_domain, val=spec) return spec def power_synthesize(self, spaces=None, real_power=True, real_signal=True): """ Yields a sampled field with `self`**2 as its power spectrum. ... ...
 ... ... @@ -38,3 +38,5 @@ from .response_operator import ResponseOperator from .laplace_operator import LaplaceOperator from .smoothness_operator import SmoothnessOperator from .power_projection_operator import PowerProjectionOperator