COMPASS  5.4.4
End-to-end AO simulation tool using GPU acceleration
wfs_util.py
1 import numpy as np
2 from astropy.io import fits
3 
4 
5 wfs_fits_content="""
6  The primary header contains the keywords:
7  * TYPE : the WFS type (only supported for now sh:shack-hartmann).
8 
9  * XCENTER, YCENTER are the coordinates of the centre of the pupil, expressed in pixels,
10  in a reference frame conformable to (i,j) coords. The translation from pixels to meters
11  can be done using:
12  meters = (pixels - XCENTER) * PIXSIZE
13 
14  * PIXSIZE : the size of the pixels on the maps in meters.
15 
16  * PUPM is the diameter of pupil stop (meters).
17 
18  * SUBAPD : the subaperture diameter (meters) i.e. the side of the subaperture square.
19 
20  This FITS file contains a single extension:
21  * Extension 'XPOS_YPOS' are the coordinates (xpos, ypos) of the bottom left corner of the
22  subapertures in the pupil (in meters).
23 """
24 
25 def add_doc_content(*content):
26  """adds content to a docstring (to be used as decorator)"""
27  def dec(obj):
28  obj.__doc__ = obj.__doc__.format(content)
29  return obj
30  return dec
31 
32 
33 def write_wfs_custom_fits(file_name:str, WFS_type:str, xpos : np.ndarray, ypos :np.ndarray,
34  xcenter, ycenter,pixsize, pupm,subap_diam) -> fits.HDUList:
35  """Write a custom_wfs fits file based on user provided data
36 
37  Args:
38  file_name : (str) : name of the wfs fits file
39 
40  WFS_type : (str) : the wfs type (sh:shack-hartmann)
41 
42  xpos : (np.ndarray): x coordinate of the bottom left corner of the subapertures
43  in the pupil (meters)
44 
45  ypos : (np.ndarray): y coordinate of the bottom left corner of the subapertures
46  in the pupil (meters)
47 
48  xcenter : (float) : x coordinate of the centre of the pupil, expressed in pixels
49 
50  ycenter : (float) : y coordinate of the centre of the pupil, expressed in pixels
51 
52  pixsize : (float) : size of the pixels on the maps in meters
53 
54  pupm : (float) : diameter of pupil stop (meters).
55 
56  subap_diam: (float) : subaperture diameter (meters) i.e. side of the subaperture square.
57 
58  Returns:
59  (HDUList) : wfs data
60 
61  """
62  if(WFS_type != 'sh'):
63  raise RuntimeError("Only Shack-Hartmann ('sh') supported at the moment")
64  fits_version=1.2
65  primary_hdu = fits.PrimaryHDU()
66  primary_hdu.header['VERSION'] = (fits_version, 'file format version')
67  primary_hdu.header['TYPE'] = (WFS_type , 'WFS type')
68  primary_hdu.header['XCENTER'] = (xcenter , 'WFS centre along X in pixels')
69  primary_hdu.header['YCENTER'] = (ycenter , 'WFS centre along Y in pixels')
70  primary_hdu.header['PIXSIZE'] = (pixsize , 'pixel size (meters)')
71  primary_hdu.header['PUPM'] = (pupm , 'nominal pupil diameter (meters)')
72  primary_hdu.header['SUBAPD'] = (subap_diam , 'subaperture diameter (pix):side of the subap')
73 
74  xpos_ypos = np.c_[xpos, ypos].T.astype(np.float64)
75  image_hdu = fits.ImageHDU(xpos_ypos, name="XPOS_YPOS")
76  custom_wfs = fits.HDUList([primary_hdu, image_hdu])
77  custom_wfs.writeto(file_name, overwrite=True)
78  return custom_wfs
79 
80 @add_doc_content(wfs_fits_content)
81 def export_custom_wfs(file_name:str, p_wfs, p_geom, *, p_tel=None):
82  """Return an HDUList (FITS) with the data required for a WFS
83 
84  and write the associated fits file
85 
86  {}
87 
88  Args :
89  file_name : (str) : name of the wfs fits file
90 
91  p_wfs : (Param_wfs) : wfs settings
92 
93  """
94  pixsize = p_geom.get_pixsize()
95  diam = p_geom.pupdiam * p_geom._pixsize
96  if(p_tel is not None):
97  diam = p_tel.diam
98  diam_pix = p_wfs.get_validsubsx().max()+ p_wfs.npix - p_wfs.get_validsubsx().min()
99  scale = diam / diam_pix
100  if( p_wfs.get_validsubsx().max()*scale+p_wfs.get_subapd()- diam != 0):
101  print("WARNING : provided diameter does not match exactly the wfs settings")
102  print(" the wfs settings span a diameter of {}m (procided : {})".format(
103  p_wfs.get_validsubsx().max()*scale+p_wfs.get_subapd(), diam
104  ))
105 
106  xpos = p_wfs.get_validpuppixx()
107  ypos = p_wfs.get_validpuppixy()
108  centerx = (xpos.max()+ p_wfs.npix + xpos.min())/2
109  centery = (ypos.max()+ p_wfs.npix + xpos.min())/2
110  wfs_custom = write_wfs_custom_fits(file_name, p_wfs.type, xpos, ypos, centerx, centery, pixsize,
111  diam, p_wfs.npix)
112  return wfs_custom
def export_custom_wfs(str file_name, p_wfs, p_geom, *p_tel=None)
Return an HDUList (FITS) with the data required for a WFS.
Definition: wfs_util.py:95
fits.HDUList write_wfs_custom_fits(str file_name, str WFS_type, np.ndarray xpos, np.ndarray ypos, xcenter, ycenter, pixsize, pupm, subap_diam)
Write a custom_wfs fits file based on user provided data.
Definition: wfs_util.py:61
def add_doc_content(*content)
adds content to a docstring (to be used as decorator)
Definition: wfs_util.py:26