def _initializeFunctionsForZernikeComputations(self, j, k, spat_freqs, a1,
                                                   a2):
        nj, mj = ZernikeGenerator.degree(j)
        nk, mk = ZernikeGenerator.degree(k)

        deltaj = math.kroneckerDelta(0, mj)
        deltak = math.kroneckerDelta(0, mk)

        if self._xp == cp:
            r1 = cp.array(self._ap1Radius)
            r2 = cp.array(self._ap2Radius)
            b1 = math.besselFirstKindOnGPU(
                nj + 1, 2 * self._xp.pi * spat_freqs * r1 * (1 - a1))
            b2 = math.besselFirstKindOnGPU(
                nk + 1, 2 * self._xp.pi * spat_freqs * r2 * (1 - a2))
        elif self._xp == np:
            r1 = self._ap1Radius
            r2 = self._ap2Radius
            b1 = math.besselFirstKind(
                nj + 1, 2 * self._xp.pi * spat_freqs * r1 * (1 - a1))
            b2 = math.besselFirstKind(
                nk + 1, 2 * self._xp.pi * spat_freqs * r2 * (1 - a2))

        c0 = (-1)**mk * self._xp.sqrt(
            (nj + 1) * (nk + 1)) * 1j**(nj + nk) * 2**(1 - 0.5 *
                                                       (deltaj + deltak))
        c1 = 1. / (self._xp.pi * r1 * r2 * (1 - a1) * (1 - a2))

        return nj, mj, nk, mk, deltaj, deltak, b1, b2, c0, c1
Esempio n. 2
0
    def _synthZernikeRecFromWavefront(self, nModes, radiusInPixels):
        diameterInPixels = 2 * radiusInPixels
        zg = ZernikeGenerator(diameterInPixels)
        wf = zg.getZernikeDict(list(range(2, 2 + nModes)))
        im = np.zeros((nModes, wf[2].compressed().size))
        modesIdx = list(range(2, 2 + nModes))

        i = 0
        for idx in modesIdx:
            im[i, :] = wf[idx].compressed()
            i += 1
        return pinv2(im)
Esempio n. 3
0
    def _synthZernikeRecFromSlopes(self, nModes, radiusInPixels):
        diameterInPixels = 2 * radiusInPixels
        zg = ZernikeGenerator(diameterInPixels)
        dx = zg.getDerivativeXDict(list(range(2, 2 + nModes)))
        dy = zg.getDerivativeYDict(list(range(2, 2 + nModes)))
        im = np.zeros((nModes, 2 * dx[2].compressed().size))
        modesIdx = list(range(2, 2 + nModes))

        i = 0
        for idx in modesIdx:
            im[i, :] = np.hstack((dx[idx].compressed(), dy[idx].compressed()))
            i += 1
        return pinv2(im)
Esempio n. 4
0
 def makeMovieOfPhase(self, nModes, outputFile='phase.mp4'):
     zg = ZernikeGenerator(200)
     imas = np.swapaxes(
         np.dstack(
             [zg.getZernike(m).filled(0) for m in np.arange(1, nModes)]), 2,
         0)
     self._makeMovie(imas, outputFile=outputFile, fps=10)
 def testDegree(self):
     m, n = ZernikeGenerator.degree(1)
     self.assertEqual(m, 0)
     self.assertEqual(n, 0)
     m, n = ZernikeGenerator.degree(2)
     self.assertEqual(m, 1)
     self.assertEqual(n, 1)
     m, n = ZernikeGenerator.degree(3)
     self.assertEqual(m, 1)
     self.assertEqual(n, 1)
     m, n = ZernikeGenerator.degree(4)
     self.assertEqual(m, 2)
     self.assertEqual(n, 0)
     m, n = self.generator.degree(2000000)
     self.assertEqual(m, 1999)
     self.assertEqual(n, 999)
Esempio n. 6
0
    def makeMovieOfRightSingularValues(self, noiseProp, outputFile='rsv.mp4'):
        zg = ZernikeGenerator(200)

        def getRightSingularMode(mIdx):
            wf = 0. * zg.getZernike(1)
            for (m, c) in zip(noiseProp.modesVector, noiseProp.v[mIdx, :]):
                wf += c * zg.getZernike(m)
            return wf

        imas = np.swapaxes(
            np.dstack([
                getRightSingularMode(mIdx)
                for mIdx in np.arange(len(noiseProp.modesVector))
            ]), 2, 0)
        self._makeMovie(imas, outputFile=outputFile, fps=10)
        return imas
 def setUp(self):
     self._nPixels = 10
     self.generator = ZernikeGenerator(self._nPixels)
class TestZernikeGenerator(unittest.TestCase):
    def setUp(self):
        self._nPixels = 10
        self.generator = ZernikeGenerator(self._nPixels)

    def testPiston(self):
        piston = self.generator[1]
        self.assertEqual(piston.shape, (self._nPixels, self._nPixels))
        self.assertTrue(piston.mask[0, 0])
        self.assertAlmostEqual(piston[self._nPixels // 2, self._nPixels // 2],
                               1.)

    def testTilt(self):
        nPx = 128
        generator = ZernikeGenerator(nPx)
        tilt = generator[3]
        self.assertAlmostEqual(tilt[-1, nPx // 2], 2. * (1 - 1. / nPx))

    def testOdd(self):
        nPx = 137
        generator = ZernikeGenerator(nPx)
        tilt = generator[17]
        self.assertAlmostEqual(tilt[int(nPx / 2.), int(nPx / 2.)], 0.)

    def testDegree(self):
        m, n = ZernikeGenerator.degree(1)
        self.assertEqual(m, 0)
        self.assertEqual(n, 0)
        m, n = ZernikeGenerator.degree(2)
        self.assertEqual(m, 1)
        self.assertEqual(n, 1)
        m, n = ZernikeGenerator.degree(3)
        self.assertEqual(m, 1)
        self.assertEqual(n, 1)
        m, n = ZernikeGenerator.degree(4)
        self.assertEqual(m, 2)
        self.assertEqual(n, 0)
        m, n = self.generator.degree(2000000)
        self.assertEqual(m, 1999)
        self.assertEqual(n, 999)

    def testRmn(self):
        self.assertTrue(
            np.allclose(self.generator._rnm(0, 0, np.array([0, 0.5, 1])),
                        np.array([1, 1, 1])))
        self.assertTrue(
            np.allclose(self.generator._rnm(1, 1, np.array([0, 0.5, 1])),
                        np.array([0, 0.5, 1])))
        self.assertTrue(
            np.allclose(self.generator._rnm(2, 0, np.array([0, 0.5, 1])),
                        np.array([-1, -0.5, 1])))
        self.assertTrue(
            np.allclose(self.generator._rnm(5, 1, np.array([0, 0.5, 1])),
                        np.array([0, 0.3125, 1])))

    def testPolar(self):
        self.assertTrue(
            np.allclose(
                self.generator._polar(1, np.array([0, 0.5, 1]),
                                      np.array([0, 1, 5]) * np.pi / 4),
                np.array([1, 1, 1])))
        self.assertTrue(
            np.allclose(
                self.generator._polar(2, np.array([0, 0.5, 1]),
                                      np.array([0, 1, 5]) * np.pi / 3),
                np.array([0, 0.5, 1])))
        self.assertTrue(
            np.allclose(
                self.generator._polar(3, np.array([0, 0.5, 1]),
                                      np.array([0, 1, 5]) * np.pi / 3),
                np.array([0, 0.866025, -1.73205])))
        self.assertTrue(
            np.allclose(
                self.generator._polar(16, np.array([0, 0.5, 1]),
                                      np.array([0, 1, 5]) * np.pi / 3),
                np.array([0, 0.541266, 1.73205])))

    def testDerivativeX(self):
        gammaX = self.generator._derivativeCoeffX(30)
        self.assertAlmostEqual(gammaX[1, 0], 2)
        self.assertAlmostEqual(gammaX[15, 3], 6)
        self.assertAlmostEqual(gammaX[16, 4], 3 * np.sqrt(2))

    def testDerivativeX2(self):
        gammaX = self.generator._derivativeCoeffX(2)
        self.assertTrue(np.allclose(gammaX, np.array([[0., 0.], [2., 0.]])),
                        "%s" % str(gammaX))

    def testDerivativeY3(self):
        gammaY = self.generator._derivativeCoeffY(3)
        self.assertTrue(
            np.allclose(gammaY,
                        np.array([[0., 0., 0.], [0., 0., 0.], [2., 0., 0.]])),
            "%s" % str(gammaY))

    def testDerivativeY(self):
        gammaY = self.generator._derivativeCoeffY(30)
        self.assertAlmostEqual(gammaY[2, 0], 2)
        self.assertAlmostEqual(gammaY[16, 3], 6)
        self.assertAlmostEqual(gammaY[9, 4], -2 * np.sqrt(3))

    def testRmsIsOne(self):
        zg = ZernikeGenerator(512)
        self.assertAlmostEqual(1., np.std(zg.getZernike(4)), 4)

    def testGetItem(self):
        a = self.generator[2]
        b = self.generator.getZernike(2)
        self.assertTrue(np.allclose(a, b))

    def testGetZernikeDict(self):
        dd = self.generator.getZernikeDict([1, 2, 10])
        self.assertTrue(np.allclose([1, 2, 10], list(dd.keys())))
        self.assertTrue(np.allclose(dd[10], self.generator.getZernike(10)))

    def testGetDerivativeOfTip(self):
        got = self.generator.getDerivativeX(2)
        wanted = 2 * np.ones((self._nPixels, self._nPixels))
        self.assertTrue(np.allclose(wanted, got),
                        "got %s, wanted %s" % (str(got), str(wanted)))
        got = self.generator.getDerivativeY(2)
        wanted = 0. * np.ones((self._nPixels, self._nPixels))
        self.assertTrue(np.allclose(wanted, got),
                        "got %s, wanted %s" % (str(got), str(wanted)))

    def testGetDerivativeOfTilt(self):
        got = self.generator.getDerivativeX(3)
        wanted = 0. * np.ones((self._nPixels, self._nPixels))
        self.assertTrue(np.allclose(wanted, got),
                        "got %s, wanted %s" % (str(got), str(wanted)))
        got = self.generator.getDerivativeY(3)
        wanted = 2. * np.ones((self._nPixels, self._nPixels))
        self.assertTrue(np.allclose(wanted, got),
                        "got %s, wanted %s" % (str(got), str(wanted)))
 def testOdd(self):
     nPx = 137
     generator = ZernikeGenerator(nPx)
     tilt = generator[17]
     self.assertAlmostEqual(tilt[int(nPx / 2.), int(nPx / 2.)], 0.)
 def testTilt(self):
     nPx = 128
     generator = ZernikeGenerator(nPx)
     tilt = generator[3]
     self.assertAlmostEqual(tilt[-1, nPx // 2], 2. * (1 - 1. / nPx))
 def testRmsIsOne(self):
     zg = ZernikeGenerator(512)
     self.assertAlmostEqual(1., np.std(zg.getZernike(4)), 4)
 def __init__(self, nSubaps=3, modesV=np.arange(1, 7), rcond=0.001):
     self._nSubaps = nSubaps
     self._zg = ZernikeGenerator(nSubaps)
     self._modesV = modesV
     self._rcond = rcond
     self._computeForModes()
class NoisePropagation():
    def __init__(self, nSubaps=3, modesV=np.arange(1, 7), rcond=0.001):
        self._nSubaps = nSubaps
        self._zg = ZernikeGenerator(nSubaps)
        self._modesV = modesV
        self._rcond = rcond
        self._computeForModes()

    def _computeForModes(self):
        self._phi = np.dstack(
            [self._zg.getZernike(m).filled(0) for m in self._modesV])
        self._D = np.vstack([
            np.hstack((self._zg.getDerivativeX(m).flatten(),
                       self._zg.getDerivativeY(m).flatten()))
            for m in self._modesV
        ]).T
        self._u, self._s, self._vh = np.linalg.svd(self._D,
                                                   full_matrices=False)
        self._sinv = 1 / self._s
        self._sinv[np.argwhere(self._s < self._rcond * self._s.max())] = 0
        self._R = np.matmul(self._vh.T,
                            np.matmul(np.diag(self._sinv), self._u.T))

    @property
    def nSubaps(self):
        return self._nSubaps

    @property
    def nSlopes(self):
        return self._D.shape[0]

    @property
    def modesVector(self):
        return self._modesV

    @property
    def nModes(self):
        return self._D.shape[1]

    @property
    def phaseCube(self):
        return self._phi

    @property
    def R(self):
        return self._R

    @property
    def D(self):
        return self._D

    @property
    def s(self):
        return self._s

    @property
    def sInv(self):
        return self._sinv

    @property
    def u(self):
        return self._u

    @property
    def v(self):
        return self._vh.T

    @property
    def noisePropagationMatrix(self):
        return np.dot(self.R, self.R.T)

    @property
    def sigma(self):
        return np.trace(self.noisePropagationMatrix)

    def noiseSimulation(self, sigma=1, nSamples=1000):
        return np.var(np.dot(self.R,
                             sigma * np.random.randn(self.nSlopes, nSamples)),
                      axis=1)

    def slopesMapForMode(self, nMode):
        return self.D[:, nMode].filled(0).reshape(self.nSubaps * 2,
                                                  self.nSubaps)

    def leftSingularVectorMapForMode(self, nMode):
        return self.u[:, nMode].filled(0).reshape(self.nSubaps * 2,
                                                  self.nSubaps)