def test_numpy_fft(self): """ Test the numpy backend against native fft. Results should be exactly the same. """ trinfos = self.param["transform_infos"] trdim = self.param["trdim"] ndim = len(self.param["size"]) input_data = self.param["test_data"].data_refs[ndim].astype(trinfos.modes[self.param["mode"]]) np_fft, np_ifft = self.transforms[trdim][np.isrealobj(input_data)] F = FFT( template=input_data, axes=trinfos.axes[trdim], backend="numpy" ) # Test FFT res = F.fft(input_data) ref = np_fft(input_data) self.assertTrue(np.allclose(res, ref)) # Test IFFT res2 = F.ifft(res) ref2 = np_ifft(ref) self.assertTrue(np.allclose(res2, ref2))
def test_fft(self): err = self.check_current_backend() if err is not None: self.skipTest(err) if self.size == "3D" and test_options.TEST_LOW_MEM: self.skipTest("low mem") ndim = len(self.size) input_data = self.test_data.data_refs[ndim].astype(self.transform_infos.modes[self.mode]) tol = self.tol[np.dtype(input_data.dtype)] if self.trdim == "3D": tol *= 10 # Error is relatively high in high dimensions # Python < 3.5 does not want to mix **extra_args with existing kwargs fft_args = { "template": input_data, "axes": self.transform_infos.axes[self.trdim], "backend": self.backend, } fft_args.update(self.extra_args) F = FFT( **fft_args ) F_np = FFT( template=input_data, axes=self.transform_infos.axes[self.trdim], backend="numpy" ) # Forward FFT res = F.fft(input_data) res_np = F_np.fft(input_data) mae = self.calc_mae(res, res_np) self.assertTrue( mae < np.abs(input_data.max()) * tol, "FFT %s:%s, MAE(%s, numpy) = %f" % (self.mode, self.trdim, self.backend, mae) ) # Inverse FFT res2 = F.ifft(res) mae = self.calc_mae(res2, input_data) self.assertTrue( mae < tol, "IFFT %s:%s, MAE(%s, numpy) = %f" % (self.mode, self.trdim, self.backend, mae) )
def __test(self, trdim, mode, size): logger.debug("trdim: %s, mode: %s, size: %s", trdim, mode, str(size)) ndim = len(size) input_data = self.test_data.data_refs[ndim].astype( self.transform_infos.modes[mode]) np_fft, np_ifft = self.transforms[trdim][np.isrealobj(input_data)] F = FFT(template=input_data, axes=self.transform_infos.axes[trdim], backend="numpy") # Test FFT res = F.fft(input_data) ref = np_fft(input_data) self.assertTrue(np.allclose(res, ref)) # Test IFFT res2 = F.ifft(res) ref2 = np_ifft(ref) self.assertTrue(np.allclose(res2, ref2))
def __test(self, backend, trdim, mode, size, **extra_args): """Compare given backend with numpy for given conditions""" logger.debug("backend: %s, trdim: %s, mode: %s, size: %s", backend, trdim, mode, str(size)) if size == "3D" and self.test_options.TEST_LOW_MEM: self.skipTest("low mem") ndim = len(size) input_data = self.test_data.data_refs[ndim].astype( self.transform_infos.modes[mode]) tol = self.tol[np.dtype(input_data.dtype)] if trdim == "3D": tol *= 10 # Error is relatively high in high dimensions # It seems that cuda has problems with C2D batched 1D if trdim == "batched_1D" and backend == "cuda" and mode == "C2C": tol *= 10 # Python < 3.5 does not want to mix **extra_args with existing kwargs fft_args = { "template": input_data, "axes": self.transform_infos.axes[trdim], "backend": backend, } fft_args.update(extra_args) F = FFT( **fft_args ) F_np = FFT( template=input_data, axes=self.transform_infos.axes[trdim], backend="numpy" ) # Forward FFT res = F.fft(input_data) res_np = F_np.fft(input_data) mae = self.calc_mae(res, res_np) all_close = np.allclose(res, res_np, atol=tol, rtol=tol), self.assertTrue( all_close, "FFT %s:%s, MAE(%s, numpy) = %f (tol = %.2e)" % (mode, trdim, backend, mae, tol) ) # Inverse FFT res2 = F.ifft(res) mae = self.calc_mae(res2, input_data) self.assertTrue( mae < tol, "IFFT %s:%s, MAE(%s, numpy) = %f" % (mode, trdim, backend, mae) )