def _generateSubHarmonics(self, numberOfSubHarmonics): nSub = 3 lowFreqScreen = np.zeros((self._screenSzInPx, self._screenSzInPx), dtype=np.complex) freqX = bfft.frequencies_x_map(nSub, 1. / nSub) freqY = bfft.frequencies_y_map(nSub, 1. / nSub) freqMod = bfft.frequencies_norm_map(nSub, 1. / nSub) vv = np.arange(self._screenSzInPx) / self._screenSzInPx xx = np.tile(vv, (self._screenSzInPx, 1)) yy = xx.T depth = 0 while depth < numberOfSubHarmonics: depth += 1 phase = self._randomPhase() freqMod /= nSub freqX /= nSub freqY /= nSub modul = self._kolmogorovAmplitudeMap(freqMod) for ix in range(nSub): for jx in range(nSub): sh = np.exp(2 * np.pi * 1j * (xx * freqX[ix, jx] + yy * freqY[ix, jx] + phase[ix, jx])) sh0 = sh.sum() / self._screenSzInPx**2 lowFreqScreen += 1. / nSub**depth * modul[ix, jx] * (sh - sh0) lowFreqScreen *= np.sqrt(0.0228) * self._screenSzInPx**(5. / 6) return lowFreqScreen
def __init__(self, dPupInMeters, r0At500nm, wavelenghtInMeters, dPupInPixels=1024, outerScaleInMeter=1e6): self._pupDiameterInMeters = dPupInMeters self._r0 = r0At500nm self._lambda = wavelenghtInMeters self._pupDiameterInPixels = dPupInPixels self._L0 = outerScaleInMeter self._tb = TurbulentPhase() self._pxSize = self._pupDiameterInMeters / self._pupDiameterInPixels self._spat_freqs = bfft.frequencies_norm_map(self._pupDiameterInPixels, self._pxSize) self._dist = bfft.distances_norm_map(self._pupDiameterInPixels, self._pxSize) self._mapCenter = (np.asarray(self._dist.shape) / 2).astype(np.int) self._psd = self._tb.vonKarmanPowerSpectralDensity( self._r0, self._L0, self._spat_freqs) self._phaseAC = bfft.direct_transform(self._psd).real self._phaseSTF = 2 * ( self._phaseAC[self._mapCenter[0], self._mapCenter[1]] - self._phaseAC) self._kolmSTFInRad2 = 6.88 * ( self._dist / r0AtLambda(self._r0, self._lambda))**(5 / 3)
def test_inverse_of_direct_return_original(self): sz = 4 spatial_step = 1.0 ampl = 1.0 xy = DomainXY.from_shape((sz, sz), spatial_step) constant_map = ampl * np.ones(xy.shape) original = ScalarBidimensionalFunction(constant_map, domain=xy) spectr = bfft.direct(original) inverse_spectr = bfft.inverse(spectr) self.assertTrue(np.allclose(inverse_spectr.values, original.values))
def testFrequenciesYMap(self): sizeInPoints = 1022 pixelSize = 0.001 frequenciesMap = bfft.frequencies_y_map(sizeInPoints, pixelSize) sz2 = int(sizeInPoints / 2) mostPosFrequency = bfft.most_positive_frequency( sizeInPoints, pixelSize) mostNegFrequency = bfft.most_negative_frequency( sizeInPoints, pixelSize) self.assertEqual((sizeInPoints, sizeInPoints), frequenciesMap.shape) self.assertTrue(np.all(0 == frequenciesMap[sz2, :])) self.assertTrue(np.all(mostNegFrequency == frequenciesMap[0, :])) self.assertTrue(np.all(mostPosFrequency == frequenciesMap[-1, :]))
def testFrequenciesXMapOdd(self): sizeInPoints = 11 pixelSize = 0.12 frequenciesMap = bfft.frequencies_x_map(sizeInPoints, pixelSize) sz2 = int(sizeInPoints / 2) mostPosFrequency = bfft.most_positive_frequency( sizeInPoints, pixelSize) mostNegFrequency = bfft.most_negative_frequency( sizeInPoints, pixelSize) self.assertEqual((sizeInPoints, sizeInPoints), frequenciesMap.shape) self.assertTrue(np.all(0 == frequenciesMap[:, sz2])) self.assertTrue(np.all(mostNegFrequency == frequenciesMap[:, 0])) self.assertTrue(np.all(mostPosFrequency == frequenciesMap[:, -1]))
def test_shifted_domain_should_not_affect_spectrum(self): sz = 4 spatial_step = 2.54 ampl = 42.0 xy = DomainXY.from_shape((sz, sz), spatial_step) xy.shift(3, 2) values = ampl * np.ones(xy.shape) spatial_funct = ScalarBidimensionalFunction(values, domain=xy) spectr_shifted = bfft.direct(spatial_funct) xy = DomainXY.from_shape((sz, sz), spatial_step) values = ampl * np.ones(xy.shape) spatial_funct = ScalarBidimensionalFunction(values, domain=xy) spectr = bfft.direct(spatial_funct) self.assertTrue(np.allclose(spectr_shifted.values, spectr.values))
def testDirectTransformConstantMapOddSize(self): sz = 101 sz2 = int(sz / 2) constantMap = np.ones((sz, sz)) res = bfft.direct_transform(constantMap) self.assertEqual((sz, sz), res.shape) self.assertTrue(np.all(np.argwhere(res > 1e-10)[0] == (sz2, sz2))) self._checkParseval(constantMap, res)
def _checkFrequenciesNormMap(self, frequenciesMap, sizeInPoints, pixelSize): sz2 = int(sizeInPoints / 2) mostPosFrequency = bfft.most_positive_frequency( sizeInPoints, pixelSize) mostNegFrequency = bfft.most_negative_frequency( sizeInPoints, pixelSize) self.assertEqual((sizeInPoints, sizeInPoints), frequenciesMap.shape) self.assertEqual(0, frequenciesMap[sz2, sz2]) self.assertAlmostEqual(-mostNegFrequency * np.sqrt(2), frequenciesMap[0, 0]) self.assertAlmostEqual(-mostNegFrequency, frequenciesMap[0, sz2]) self.assertAlmostEqual(-mostNegFrequency, frequenciesMap[sz2, 0]) self.assertAlmostEqual(mostPosFrequency, frequenciesMap[sz2, -1]) self.assertAlmostEqual(mostPosFrequency, frequenciesMap[-1, sz2]) wantedDelta = 1. / (sizeInPoints * pixelSize) self.assertEqual(wantedDelta, frequenciesMap[sz2, sz2 + 1])
def testInverseTransformDeltaMapEvenSize(self): sz = 100 sz2 = int(sz / 2) deltaMap = np.zeros((sz, sz)) deltaMap[sz2, sz2] = 1.0 res = bfft.inverse_transform(deltaMap) self.assertEqual((sz, sz), res.shape) self.assertEqual(0, res.ptp()) self._checkParseval(deltaMap, res)
def testDirectTransformSinusX(self): sizeInPoints = 500 pixelSize = 0.2 periodInLengthUnits = 4.0 amplitude = 13.4 phase = 0.8 spatialMap = self._makeSinusMap(sizeInPoints, pixelSize, amplitude, periodInLengthUnits, phase) spectralMap = bfft.direct_transform(spatialMap) freqX = bfft.frequencies_x_map(sizeInPoints, pixelSize) freqY = bfft.frequencies_y_map(sizeInPoints, pixelSize) self.assertEqual((sizeInPoints, sizeInPoints), spectralMap.shape) self.assertEqual( 1.0 / periodInLengthUnits, np.abs(freqX.flatten()[np.argmax(np.abs(spectralMap))])) self.assertEqual( 0.0, np.abs(freqY.flatten()[np.argmax(np.abs(spectralMap))])) self._checkParseval(spatialMap, spectralMap)
def testInverseDeltaMapEvenSize(self): sz = 100 sz2 = int(sz / 2) deltaMap = np.zeros((sz, sz)) deltaMap[sz2, sz2] = 1.0 xyDomain = DomainXY.from_shape((sz, sz), 1) xyFunct = ScalarBidimensionalFunction(deltaMap, domain=xyDomain) fftFunct = bfft.inverse(xyFunct) spectralMap = fftFunct.values self.assertEqual((sz, sz), spectralMap.shape) self.assertEqual(0, spectralMap.ptp()) self._checkParseval(deltaMap, spectralMap)
def test_direct_sinus_x(self): sizeInPoints = 500 pixelSize = 0.2 periodInLengthUnits = 4.0 amplitude = 13.4 phase = 0.8 spatialMap = self._makeSinusMap(sizeInPoints, pixelSize, amplitude, periodInLengthUnits, phase) xyDomain = DomainXY.from_shape((sizeInPoints, sizeInPoints), pixelSize) xyFunct = ScalarBidimensionalFunction(spatialMap, domain=xyDomain) fftFunct = bfft.direct(xyFunct) spectralMap = fftFunct.values freqX = bfft.frequencies_x_map(sizeInPoints, pixelSize) freqY = bfft.frequencies_y_map(sizeInPoints, pixelSize) self.assertEqual((sizeInPoints, sizeInPoints), spectralMap.shape) self.assertEqual( 1.0 / periodInLengthUnits, np.abs(freqX.flatten()[np.argmax(np.abs(spectralMap))])) self.assertEqual( 0.0, np.abs(freqY.flatten()[np.argmax(np.abs(spectralMap))])) self._checkParseval(spatialMap, spectralMap)
def test_inverse_units(self): from astropy import units as u szx, szy = (20, 10) stepx, stepy = (0.1 * u.m, 0.4 * u.kg) ampl = 1.0 * u.V xy = DomainXY.from_shape((szy, szx), (stepy, stepx)) map_in_V = ampl * np.ones(xy.shape) spatial_funct = ScalarBidimensionalFunction(map_in_V, domain=xy) spectr = bfft.inverse(spatial_funct) self.assertTrue(spectr.xmap.unit.is_equivalent((1 / u.m).unit)) self.assertTrue(spectr.ymap.unit.is_equivalent((1 / u.kg).unit)) self.assertTrue(spectr.xcoord.unit.is_equivalent((1 / u.m).unit)) self.assertTrue(spectr.ycoord.unit.is_equivalent((1 / u.kg).unit)) self.assertTrue(spectr.values.unit.is_equivalent((u.V)))
def test_rectangular_domain(self): szx, szy = (20, 10) stepx, stepy = (0.1, 0.4) ampl = 1.0 xy = DomainXY.from_shape((szy, szx), (stepy, stepx)) constant_map = ampl * np.ones(xy.shape) spatial_funct = ScalarBidimensionalFunction(constant_map, domain=xy) spectr = bfft.direct(spatial_funct) freq_step_x, freq_step_y = spectr.domain.step self.assertAlmostEqual(0, spectr.xmap[szy // 2, szx // 2]) self.assertAlmostEqual(0, spectr.ymap[szy // 2, szx // 2]) self.assertAlmostEqual(np.sqrt(ampl * szx * szy), spectr.values[szy // 2, szx // 2]) self.assertAlmostEqual(-0.5 / stepx, spectr.xcoord[0]) self.assertAlmostEqual(1 / (szx * stepx), freq_step_x) self.assertAlmostEqual(-0.5 / stepy, spectr.ycoord[0]) self.assertAlmostEqual(1 / (szy * stepy), freq_step_y)
def _createPsf(self): psf = bfft.inverse(self.otf()) rescaleCoordFact = 1 / self._focalLength self._psf = S2DF(psf.values(), psf.xCoord() * rescaleCoordFact, psf.yCoord() * rescaleCoordFact)
def _createPupilPlaneCoordinatesInMeters(self): return bfft.distances_x_map( self.focalPlaneSizeInPixels(), self.pupilPlanePixelSizeInMeters())
def _autoCorrelate(self, scalar2dfunct): functFT = bfft.direct(scalar2dfunct) aa = S2DF(np.abs(functFT.values() ** 2), functFT.xCoord(), functFT.yCoord()) return bfft.inverse(aa)
def testFrequenciesMapEvenWithPixelSize(self): sizeInPoints = 100 pxSize = 0.1 freqs = bfft.frequencies_norm_map(sizeInPoints, pxSize) self._checkFrequenciesNormMap(freqs, sizeInPoints, pxSize)
def _createFocalPlaneCoordinatesInArcSec(self): return bfft.distances_x_map( self.focalPlaneSizeInPixels(), self.focalPlanePixelSizeInArcsec())
def _createPupilPlaneSpatialFrequencyCoordiantesInInverseMeters(self): return bfft.frequencies_x_map( self.focalPlaneSizeInPixels(), self.pupilPlanePixelSizeInMeters())
def testFrequenciesMapEven(self): sz = 100 pixelSize = 1.0 freqs = bfft.frequencies_norm_map(sz, pixelSize) self._checkFrequenciesNormMap(freqs, sz, pixelSize)
def _createFocalPlaneAngularFrequencyCoordinatesInInverseRadians(self): return bfft.frequencies_x_map( self.focalPlaneSizeInPixels(), self.focalPlanePixelSizeInArcsec() * self.ARCSEC2RAD)