Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1#!/usr/bin/env python 

2# encoding: utf-8 

3""" 

4*Recipe to generate a first approximation of the dispersion solution from single pinhole frames* 

5 

6:Author: 

7 David Young & Marco Landoni 

8 

9:Date Created: 

10 August 25, 2020 

11""" 

12################# GLOBAL IMPORTS #################### 

13from builtins import object 

14import sys 

15import os 

16os.environ['TERM'] = 'vt100' 

17from fundamentals import tools 

18from soxspipe.commonutils import set_of_files 

19from ._base_recipe_ import _base_recipe_ 

20import numpy as np 

21from astropy.nddata import CCDData 

22from astropy import units as u 

23import ccdproc 

24from soxspipe.commonutils import keyword_lookup 

25import unicodecsv as csv 

26 

27 

28class soxs_disp_solution(_base_recipe_): 

29 """ 

30 *generate a first approximation of the dispersion solution from single pinhole frames* 

31 

32 **Key Arguments** 

33 

34 - ``log`` -- logger 

35 - ``settings`` -- the settings dictionary 

36 - ``inputFrames`` -- input fits frames. Can be a directory, a set-of-files (SOF) file or a list of fits frame paths. 

37 - ``verbose`` -- verbose. True or False. Default *False* 

38 

39 **Usage** 

40 

41 ```python 

42 from soxspipe.recipes import soxs_disp_solution 

43 disp_map_path = soxs_disp_solution( 

44 log=log, 

45 settings=settings, 

46 inputFrames=sofPath 

47 ).produce_product() 

48 ``` 

49 

50 ---  

51 

52 ```eval_rst 

53 .. todo:: 

54 

55 - add a tutorial about ``soxs_disp_solution`` to documentation 

56 ``` 

57 """ 

58 

59 def __init__( 

60 self, 

61 log, 

62 settings=False, 

63 inputFrames=[], 

64 verbose=False 

65 

66 ): 

67 # INHERIT INITIALISATION FROM _base_recipe_ 

68 super(soxs_disp_solution, self).__init__( 

69 log=log, settings=settings) 

70 self.log = log 

71 log.debug("instansiating a new 'soxs_disp_solution' object") 

72 self.settings = settings 

73 self.inputFrames = inputFrames 

74 self.verbose = verbose 

75 self.recipeName = "soxs-disp-solution" 

76 self.recipeSettings = settings[self.recipeName] 

77 

78 # CONVERT INPUT FILES TO A CCDPROC IMAGE COLLECTION (inputFrames > 

79 # imagefilecollection) 

80 sof = set_of_files( 

81 log=self.log, 

82 settings=self.settings, 

83 inputFrames=self.inputFrames 

84 ) 

85 self.inputFrames, self.supplementaryInput = sof.get() 

86 

87 # VERIFY THE FRAMES ARE THE ONES EXPECTED BY SOXS_disp_solution - NO MORE, NO LESS. 

88 # PRINT SUMMARY OF FILES. 

89 print("# VERIFYING INPUT FRAMES") 

90 self.verify_input_frames() 

91 sys.stdout.write("\x1b[1A\x1b[2K") 

92 print("# VERIFYING INPUT FRAMES - ALL GOOD") 

93 

94 # SORT IMAGE COLLECTION 

95 self.inputFrames.sort(['mjd-obs']) 

96 if self.verbose: 

97 print("# RAW INPUT FRAMES - SUMMARY") 

98 print(self.inputFrames.summary, "\n") 

99 

100 # PREPARE THE FRAMES - CONVERT TO ELECTRONS, ADD UNCERTAINTY AND MASK 

101 # EXTENSIONS 

102 self.inputFrames = self.prepare_frames( 

103 save=self.settings["save-intermediate-products"]) 

104 

105 return None 

106 

107 def verify_input_frames( 

108 self): 

109 """*verify input frames match those required by the `soxs_disp_solution` recipe* 

110 

111 If the fits files conform to required input for the recipe everything will pass silently, otherwise an exception shall be raised. 

112 """ 

113 self.log.debug('starting the ``verify_input_frames`` method') 

114 

115 kw = self.kw 

116 

117 # BASIC VERIFICATION COMMON TO ALL RECIPES 

118 self._verify_input_frames_basics() 

119 

120 imageTypes = self.inputFrames.values( 

121 keyword=kw("DPR_TYPE").lower(), unique=True) 

122 imageTech = self.inputFrames.values( 

123 keyword=kw("DPR_TECH").lower(), unique=True) 

124 imageCat = self.inputFrames.values( 

125 keyword=kw("DPR_CATG").lower(), unique=True) 

126 

127 if self.arm == "NIR": 

128 # WANT ON AND OFF PINHOLE FRAMES 

129 # MIXED INPUT IMAGE TYPES ARE BAD 

130 if len(imageTypes) > 1: 

131 imageTypes = " and ".join(imageTypes) 

132 print(self.inputFrames.summary) 

133 raise TypeError( 

134 "Input frames are a mix of %(imageTypes)s" % locals()) 

135 

136 if imageTypes[0] != "LAMP,FMTCHK": 

137 raise TypeError( 

138 "Input frames for soxspipe disp_solution need to be single pinhole lamp on and lamp off frames for NIR" % locals()) 

139 

140 for i in imageTech: 

141 if i not in ['ECHELLE,PINHOLE', 'IMAGE']: 

142 raise TypeError( 

143 "Input frames for soxspipe disp_solution need to be single pinhole lamp on and lamp off frames for NIR" % locals()) 

144 

145 else: 

146 for i in imageTypes: 

147 if i not in ["LAMP,FMTCHK", "BIAS", "DARK"]: 

148 raise TypeError( 

149 "Input frames for soxspipe disp_solution need to be single pinhole lamp on and a master-bias and possibly a master dark for UVB/VIS" % locals()) 

150 

151 self.imageType = imageTypes[0] 

152 self.log.debug('completed the ``verify_input_frames`` method') 

153 return None 

154 

155 def produce_product( 

156 self): 

157 """*generate a fisrt guess of the dispersion solution* 

158 

159 **Return:** 

160 - ``productPath`` -- the path to the first guess dispersion map 

161 """ 

162 self.log.debug('starting the ``produce_product`` method') 

163 

164 arm = self.arm 

165 kw = self.kw 

166 dp = self.detectorParams 

167 

168 # self.inputFrames.summary.pprint_all() 

169 

170 master_bias = False 

171 dark = False 

172 pinhole_image = False 

173 

174 add_filters = {kw("DPR_CATG"): 'MASTER_BIAS_' + arm} 

175 for i in self.inputFrames.files_filtered(include_path=True, **add_filters): 

176 master_bias = CCDData.read(i, hdu=0, unit=u.adu, hdu_uncertainty='ERRS', 

177 hdu_mask='QUAL', hdu_flags='FLAGS', key_uncertainty_type='UTYPE') 

178 

179 # UVB/VIS DARK 

180 add_filters = {kw("DPR_CATG"): 'MASTER_DARK_' + arm} 

181 for i in self.inputFrames.files_filtered(include_path=True, **add_filters): 

182 dark = CCDData.read(i, hdu=0, unit=u.adu, hdu_uncertainty='ERRS', 

183 hdu_mask='QUAL', hdu_flags='FLAGS', key_uncertainty_type='UTYPE') 

184 

185 # NIR DARK 

186 add_filters = {kw("DPR_TYPE"): 'LAMP,FMTCHK', kw("DPR_TECH"): 'IMAGE'} 

187 for i in self.inputFrames.files_filtered(include_path=True, **add_filters): 

188 dark = CCDData.read(i, hdu=0, unit=u.adu, hdu_uncertainty='ERRS', 

189 hdu_mask='QUAL', hdu_flags='FLAGS', key_uncertainty_type='UTYPE') 

190 

191 add_filters = {kw("DPR_TYPE"): 'LAMP,FMTCHK', 

192 kw("DPR_TECH"): 'ECHELLE,PINHOLE'} 

193 for i in self.inputFrames.files_filtered(include_path=True, **add_filters): 

194 pinhole_image = CCDData.read(i, hdu=0, unit=u.adu, hdu_uncertainty='ERRS', 

195 hdu_mask='QUAL', hdu_flags='FLAGS', key_uncertainty_type='UTYPE') 

196 

197 self.pinholeFrame = self.subtract_calibrations( 

198 inputFrame=pinhole_image, master_bias=master_bias, dark=dark) 

199 

200 if self.settings["save-intermediate-products"]: 

201 outDir = self.intermediateRootPath 

202 filePath = self._write( 

203 frame=self.pinholeFrame, 

204 filedir=outDir, 

205 filename=False, 

206 overwrite=True 

207 ) 

208 print(f"\nCalibrated single pinhole frame: {filePath}\n") 

209 

210 from soxspipe.commonutils import create_dispersion_map 

211 productPath = create_dispersion_map( 

212 log=self.log, 

213 settings=self.settings, 

214 pinholeFrame=self.pinholeFrame 

215 ).get() 

216 

217 self.clean_up() 

218 

219 self.log.debug('completed the ``produce_product`` method') 

220 return productPath 

221 

222 # use the tab-trigger below for new method 

223 # xt-class-method