COMPASS  5.0.0
End-to-end AO simulation tool using GPU acceleration
actuCouplingTest.py
1 # Initialize widget and load MICADO ELT pupil
2 
3 p_geom = wao.config.p_geom
4 
5 import shesha.util.make_pupil as mkP
6 import shesha.util.utilities as util
7 import scipy.ndimage
8 
9 import numpy as np
10 import matplotlib.pyplot as plt
11 plt.ion()
12 
13 cent = p_geom.pupdiam / 2. + 0.5
14 
15 p_tel = wao.config.p_tel
16 
17 p_tel.t_spiders = 0.51
18 spup = mkP.make_pupil(p_geom.pupdiam, p_geom.pupdiam, p_tel, cent,
19  cent).astype(np.float32)
20 
21 p_tel.t_spiders = 0.
22 spup2 = mkP.make_pupil(p_geom.pupdiam, p_geom.pupdiam, p_tel, cent,
23  cent).astype(np.float32)
24 
25 spiders = spup2 - spup
26 
27 (spidersID, k) = scipy.ndimage.label(spiders)
28 spidersi = util.pad_array(spidersID, p_geom.ssize).astype(np.float32)
29 pxListSpider = [np.where(spidersi == i) for i in range(1, k + 1)]
30 
31 # DM positions in iPupil:
32 dmposx = wao.config.p_dm0._xpos - 0.5
33 dmposy = wao.config.p_dm0._ypos - 0.5
34 dmposMat = np.c_[dmposx, dmposy].T # one actu per column
35 
36 pitch = wao.config.p_dm0._pitch
37 
38 plt.clf()
39 plt.scatter(*dmposMat)
40 discard = np.zeros(len(dmposx), dtype=np.bool)
41 pairs = []
42 
43 # For each of the k pieces of the spider
44 for k, pxList in enumerate(pxListSpider):
45  pts = np.c_[pxList[1], pxList[0]] # x,y coord of pixels of the spider piece
46  # lineEq = [a, b]
47  # Which minimizes leqst squares of aa*x + bb*y = 1
48  lineEq = np.linalg.pinv(pts).dot(np.ones(pts.shape[0]))
49  aa, bb = lineEq[0], lineEq[1]
50 
51  # Find any point of the fitted line.
52  # For simplicity, the intercept with one of the axes x = 0 / y = 0
53  if np.abs(bb) < np.abs(aa): # near vertical
54  onePoint = np.array([1 / aa, 0.])
55  else: # otherwise
56  onePoint = np.array([0., 1 / bb])
57  x = np.arange(2048)
58  y = -aa / bb * x + 1 / bb
59  plt.plot(x, y, color='C%u' % (4 + k), label='%u' % k)
60  plt.plot()
61 
62  # Rotation that aligns the spider piece to the horizontal
63  rotation = np.array([[-bb, aa], [-aa, -bb]]) / (aa**2 + bb**2)**.5
64 
65  # Rotated the spider mask
66  rotatedPx = rotation.dot(pts.T - onePoint[:, None])
67  # Min and max coordinates along the spider length - to filter actuators that are on
68  # 'This' side of the pupil and not the other side
69  minU, maxU = rotatedPx[0].min() - 5. * pitch, rotatedPx[0].max() + 5. * pitch
70 
71  # Rotate the actuators
72  rotatedActus = rotation.dot(dmposMat - onePoint[:, None])
73  selGoodSide = (rotatedActus[0] > minU) & (rotatedActus[0] < maxU)
74 
75  # Actuators below this piece of spider
76  selDiscard = (np.abs(rotatedActus[1]) < 0.5 * pitch) & selGoodSide
77  discard |= selDiscard
78 
79  # Actuator 'near' this piece of spider
80  selPairable = (np.abs(rotatedActus[1]) > 0.5 * pitch) & \
81  (np.abs(rotatedActus[1]) < 1.5 * pitch) & \
82  selGoodSide
83 
84  pairableIdx = np.where(selPairable)[0] # Indices of these actuators
85  uCoord = rotatedActus[0,
86  selPairable] # Their linear coord along the spider major axis
87 
88  order = np.sort(uCoord) # Sort by linear coordinate
89  orderIdx = pairableIdx[np.argsort(uCoord)] # And keep track of original indexes
90 
91  for i in range(0, len(order) - 1):
92  # Check if next actu in sorted order is very close
93  # Some lonely actuators may be hanging in this list
94  if np.abs(order[i] - order[i + 1]) < .2 * pitch:
95  pairs += [(orderIdx[i], orderIdx[i + 1])]
96 
97  plt.scatter(*dmposMat[:, selDiscard], color='C1')
98  plt.scatter(*dmposMat[:, selPairable], color='C2')
99  plt.legend(loc=0)
100 
101 for (p, q) in pairs:
102  plt.scatter(*dmposMat[:, [p, q]])
103 
104 print('To discard: %u actu' % np.sum(discard))
105 print('%u pairs to slave' % len(pairs))
shesha.util.utilities
Basic utilities function.
Definition: utilities.py:1
shesha.util.make_pupil
Pupil creation functions.
Definition: make_pupil.py:1