COMPASS  5.0.0
End-to-end AO simulation tool using GPU acceleration
calibration.py
1 
37 import numpy as np
38 
39 class Calibration(object):
40  """ This optimizer class handles all the modal basis and DM Influence functions
41  related operations.
42 
43  Attributes:
44  config : (config) : Configuration parameters module
45 
46  tel : (TelescopeCompass) : TelescopeCompass instance
47 
48  atmos : (AtmosScompass) : AtmosCompass instance
49 
50  dms : (DmCompass) : DmCompass instance
51 
52  target : (TargetCompass) : TargetCompass instance
53 
54  rtc : (RtcCompass) : RtcCompass instance
55 
56  wfs : (WfsCompass) : WfsCompass instance
57  """
58  def __init__(self, config, tel, atmos, dms, target, rtc, wfs):
59  """ Instantiate a ModalBasis object
60 
61  Parameters:
62  config : (config) : Configuration parameters module
63 
64  tel : (TelescopeCompass) : TelescopeCompass instance
65 
66  atmos : (AtmosScompass) : AtmosCompass instance
67 
68  dms : (DmCompass) : DmCompass instance
69 
70  target : (TargetCompass) : TargetCompass instance
71 
72  rtc : (RtcCompass) : RtcCompass instance
73 
74  wfs : (WfsCompass) : WfsCompass instance
75  """
76  self.config = config
77  self.tel = tel
78  self.atmos = atmos
79  self.dms = dms
80  self.target = target
81  self.rtc = rtc
82  self.wfs = wfs
83 
84  def apply_volts_and_get_slopes(self, controller_index: int, *, noise: bool = False,
85  turbu: bool = False, reset: bool = True):
86  """ Apply voltages, raytrace, compute WFS image, compute slopes and returns it
87 
88  Parameters:
89  controller_index : (int) : Controller index
90 
91  noise : (bool, optional) : Flag to enable noise for WFS image compuation. Default is False
92 
93  turbu : (bool, optional) : Flag to enable atmosphere for WFS phase screen raytracing.
94  Default is False
95 
96  reset : (bool, optional) : Flag to reset previous phase screen before raytracing.
97  Default is True
98  """
99  self.rtc.apply_control(controller_index)
100  for w in range(len(self.config.p_wfss)):
101  if (turbu):
102  self.wfs.raytrace(w, tel=self.tel, atm=self.atmos, dms=self.dms)
103  else:
104  self.wfs.raytrace(w, dms=self.dms, reset=reset)
105  self.wfs.compute_wfs_image(w, noise=noise)
106  return self.rtc.compute_slopes(controller_index)
107 
108  def do_imat_modal(self, controller_index : int, ampli : np.ndarray, modal_basis : np.ndarray,
109  *, noise : bool=False, nmodes_max : int=0, with_turbu : bool=False, push_pull : bool=False) -> np.ndarray:
110  """ Computes an interaction matrix from provided modal basis
111 
112  Parameters:
113  controller_index : (int) : Controller index
114 
115  ampli : (np.ndarray) : amplitude to apply on each mode
116 
117  modal_basis : (np.ndarray) : modal basis matrix
118 
119  noise : (bool, optional) : Flag to enable noise for WFS image compuation. Default is False
120 
121  nmodes_max : (int, optional) : Default is 0. TODO : description
122 
123  with_turbu : (bool, optional) : Flag to enable atmosphere for WFS phase screen raytracing.
124  Default is False
125 
126  push_pull : (bool, optional) : If True, imat is computed as an average of push and pull ampli
127  on each mode
128 
129  Return:
130  modal_imat : (np.ndarray) : Modal interaction matrix
131  """
132  modal_imat = np.zeros((self.config.p_controllers[controller_index].nslope, modal_basis.shape[1]))
133 
134  if (nmodes_max == 0):
135  nmodes_max = modal_basis.shape[1]
136  v_old = self.rtc.get_command(controller_index)
137  self.rtc.open_loop(controller_index, reset=False)
138  for m in range(nmodes_max):
139  v = ampli[m] * modal_basis[:, m]
140  if ((push_pull is True) or
141  (with_turbu is True)): # with turbulence/aberrations => push/pull
142  self.rtc.set_perturbation_voltage(
143  controller_index, "imat_modal",
144  v_old + v) # Adding Perturbation voltage on current iteration
145  devpos = self.apply_volts_and_get_slopes(controller_index,
146  turbu=with_turbu, noise=noise)
147  self.rtc.set_perturbation_voltage(controller_index, "imat_modal", v_old - v)
148  devmin = self.apply_volts_and_get_slopes(controller_index,
149  turbu=with_turbu, noise=noise)
150  modal_imat[:, m] = (devpos - devmin) / (2. * ampli[m])
151  else: # No turbulence => push only
152  self.rtc.open_loop(controller_index) # open_loop
153  self.rtc.set_perturbation_voltage(controller_index, "imat_modal", v)
154  modal_imat[:, m] = self.apply_volts_and_get_slopes(controller_index, noise=noise) / ampli[m]
155  self.rtc.remove_perturbation_voltage(controller_index, "imat_modal")
156  if ((push_pull is True) or (with_turbu is True)):
157  self.rtc.close_loop(controller_index) # We are supposed to be in close loop now
158  return modal_imat
159 
160  def do_imat_phase(self, controller_index: int, cube_phase: np.ndarray, *, noise : bool=False,
161  nmodes_max : int=0, with_turbu : bool=False, push_pull : bool=False, wfs_index : int=0) -> np.ndarray:
162  """ Computes an interaction matrix with the provided cube phase
163 
164  Parameters:
165  controller_index : (int) : Controller index
166 
167  cube_phase : (np.ndarray) : Cube of phase to insert as NCPA
168 
169  noise : (bool, optional) : Flag to enable noise for WFS image compuation. Default is False
170 
171  nmodes_max : (int, optional) : Default is 0. TODO : description
172 
173  with_turbu : (bool, optional) : Flag to enable atmosphere for WFS phase screen raytracing.
174  Default is False
175 
176  push_pull : (bool, optional) : If True, imat is computed as an average of push and pull ampli
177  on each mode
178 
179  wfs_index : (int, optional) : WFS index. Default is 0
180 
181  Return:
182  phase_imat : (np.ndarray) : Phase interaction matrix
183  """
184  imat_phase = np.zeros((cube_phase.shape[0], self.config.p_controllers[controller_index].nslope))
185  for nphase in range(cube_phase.shape[0]):
186  if ((push_pull is True) or (with_turbu is True)
187  ): # with turbulence/aberrations => push/pullADOPT/projects/cosmic/
188  self.wfs.set_ncpa_wfs(wfs_index, cube_phase[nphase, :, :])
189  devpos = self.apply_volts_and_get_slopes(controller_index,
190  turbu=with_turbu, noise=noise)
191  self.set_ncpa_wfs(wfs_index, -cube_phase[nphase, :, :])
192  devmin = self.apply_volts_and_get_slopes(controller_index,
193  turbu=with_turbu, noise=noise)
194  imat_phase[nphase, :] = (devpos - devmin) / 2
195  else: # No turbulence => push only
196  self.rtc.open_loop(controller_index) # open_loop
197  self.wfs.set_ncpa_wfs(wfs_index, cube_phase[nphase, :, :])
198  imat_phase[nphase, :] = self.apply_volts_and_get_slopes(
199  controller_index, noise=noise)
200  self.wfs.set_ncpa_wfs(wfs_index,
201  cube_phase[nphase, :, :] * 0.) # Remove the Phase on WFS
202  _ = self.apply_volts_and_get_slopes(controller_index, turbu=with_turbu,
203  noise=noise)
204 
205  return imat_phase
206 
207  def compute_modal_residuals(self, projection_matrix : np.ndarray,
208  *, selected_actus : np.ndarray=None) -> np.ndarray:
209  """ Computes the modal residual coefficients of the residual phase.
210 
211  /!\ It supposed that roket is enabled, and the associated GEO controller is index 1.
212 
213  Uses the projection matrix computed from compute_modes_to_volts_basis (modalBasis module)
214 
215  Parameters:
216  projection_matrix : (np.ndarray) : Modal projection matrix
217 
218  selected_actus : (np.ndarray) : TODO : description
219 
220  Return:
221  ai : (np.ndarray) : Modal coefficients
222  """
223  try:
224  self.rtc.do_control(1, sources=self.target.sources)
225  except:
226  return [0]
227  v = self.rtc.get_command(1) # We compute here the residual phase on the DM modes. Gives the Equivalent volts to apply/
228  if (selected_actus is None):
229  ai = projection_matrix.dot(v) * 1000. # np rms units
230  else: # Slaving actus case
231  v2 = v[:-2][list(
232  selected_actus)] # If actus are slaved then we select them.
233  v3 = v[-2:]
234  ai = projection_matrix.dot(np.concatenate((v2, v3))) * 1000.
235  return ai
236 
shesha.supervisor.optimizers.calibration.Calibration.compute_modal_residuals
np.ndarray compute_modal_residuals(self, np.ndarray projection_matrix, *np.ndarray selected_actus=None)
Computes the modal residual coefficients of the residual phase.
Definition: calibration.py:244
shesha.supervisor.optimizers.calibration.Calibration.wfs
wfs
Instantiate a ModalBasis object.
Definition: calibration.py:102
shesha.supervisor.optimizers.calibration.Calibration.config
config
Definition: calibration.py:96
shesha.supervisor.optimizers.calibration.Calibration.target
target
Definition: calibration.py:100
shesha.supervisor.optimizers.calibration.Calibration.dms
dms
Definition: calibration.py:99
open_loop
Definition: open_loop.py:1
shesha.supervisor.optimizers.calibration.Calibration.rtc
rtc
Definition: calibration.py:101
shesha.supervisor.optimizers.calibration.Calibration.tel
tel
Definition: calibration.py:97
shesha.supervisor.optimizers.calibration.Calibration.apply_volts_and_get_slopes
def apply_volts_and_get_slopes(self, int controller_index, *bool noise=False, bool turbu=False, bool reset=True)
Apply voltages, raytrace, compute WFS image, compute slopes and returns it.
Definition: calibration.py:117
shesha.supervisor.optimizers.calibration.Calibration.__init__
def __init__(self, config, tel, atmos, dms, target, rtc, wfs)
Definition: calibration.py:95
shesha.supervisor.optimizers.calibration.Calibration.do_imat_modal
np.ndarray do_imat_modal(self, int controller_index, np.ndarray ampli, np.ndarray modal_basis, *bool noise=False, int nmodes_max=0, bool with_turbu=False, bool push_pull=False)
Computes an interaction matrix from provided modal basis.
Definition: calibration.py:150
shesha.supervisor.optimizers.calibration.Calibration.do_imat_phase
np.ndarray do_imat_phase(self, int controller_index, np.ndarray cube_phase, *bool noise=False, int nmodes_max=0, bool with_turbu=False, bool push_pull=False, int wfs_index=0)
Computes an interaction matrix with the provided cube phase.
Definition: calibration.py:202
shesha.supervisor.optimizers.calibration.Calibration.atmos
atmos
Definition: calibration.py:98
shesha.supervisor.optimizers.calibration.Calibration
This optimizer class handles all the modal basis and DM Influence functions related operations.
Definition: calibration.py:44