Skip to content

Commit

Permalink
fall back to least squares solver when Cholesky fails for infinite ph…
Browse files Browse the repository at this point in the history
…asescreen
  • Loading branch information
bernadett92 committed Oct 16, 2024
1 parent 0401fa1 commit e5eebd1
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 6 deletions.
10 changes: 4 additions & 6 deletions aotools/turbulence/infinitephasescreen.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,16 +143,14 @@ def makeAMatrix(self):
Calculates the "A" matrix, that uses the existing data to find a new
component of the new phase vector.
"""
# Cholsky solve can fail - if so do brute force inversion
try:
cf = linalg.cho_factor(self.cov_mat_zz)
inv_cov_zz = linalg.cho_solve(cf, numpy.identity(self.cov_mat_zz.shape[0]))
self.A_mat = self.cov_mat_xz.dot(inv_cov_zz)
except linalg.LinAlgError:
# print("Cholesky solve failed. Performing SVD inversion...")
# inv_cov_zz = numpy.linalg.pinv(self.cov_mat_zz)
raise linalg.LinAlgError("Could not invert Covariance Matrix to for A and B Matrices. Try with a larger pixel scale or smaller L0")

self.A_mat = self.cov_mat_xz.dot(inv_cov_zz)
print("Cholesky solve failed. Performing least squares inversion...")
inv_cov_zz = numpy.linalg.lstsq(self.cov_mat_zz, numpy.identity(self.cov_mat_zz.shape[0]), rcond=1e-8)
self.A_mat = self.cov_mat_xz.dot(inv_cov_zz[0])

def makeBMatrix(self):
"""
Expand Down
10 changes: 10 additions & 0 deletions test/test_infinitephasescreen.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from aotools.turbulence import infinitephasescreen
import numpy as np

def testVKInitScreen():

Expand All @@ -9,6 +10,15 @@ def testVKAddRow():
scrn = infinitephasescreen.PhaseScreenVonKarman(128, 4./64, 0.2, 50, n_columns=4)
scrn.add_row()

def testLeastSquaresSolver():
airmass = 1.0 / np.cos(30.0 / 180. * np.pi)
r0 = 0.9759 * 0.5 / (0.7 * 4.848) * airmass ** (-3. / 5.)
r0wavelength = r0 * (500 / 500.0) ** (6. / 5.)
screen = infinitephasescreen.PhaseScreenVonKarman(120, 1./120, r0wavelength, 50, 1, n_columns=2)
mean_scrn = np.sqrt(np.mean(screen.scrn**2))
for i in range(500):
screen.add_row()
assert(0.5 <= mean_scrn/np.sqrt(np.mean(screen.scrn**2)) <= 1.5)


# Test of Kolmogoroc screen
Expand Down

0 comments on commit e5eebd1

Please sign in to comment.