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*further constrain the first guess locations of the order centres derived in `soxs_disp_solution`* 

5 

6:Author: 

7 David Young & Marco Landoni 

8 

9:Date Created: 

10 September 8, 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 

25from soxspipe.commonutils import detect_continuum 

26 

27 

28class soxs_order_centres(_base_recipe_): 

29 """ 

30 *The soxs_order_centres recipe* 

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 

38 **Usage** 

39 

40 ```python 

41 from soxspipe.recipes import soxs_order_centres 

42 order_table = soxs_order_centres( 

43 log=log, 

44 settings=settings, 

45 inputFrames=a["inputFrames"] 

46 ).produce_product() 

47 ``` 

48 

49 --- 

50 

51 ```eval_rst 

52 .. todo:: 

53 

54 - add a tutorial about ``soxs_order_centres`` to documentation 

55 ``` 

56 """ 

57 # Initialisation 

58 

59 def __init__( 

60 self, 

61 log, 

62 settings=False, 

63 inputFrames=[] 

64 

65 ): 

66 # INHERIT INITIALISATION FROM _base_recipe_ 

67 super(soxs_order_centres, self).__init__( 

68 log=log, settings=settings) 

69 self.log = log 

70 log.debug("instansiating a new 'soxs_order_centres' object") 

71 self.settings = settings 

72 self.inputFrames = inputFrames 

73 # xt-self-arg-tmpx 

74 

75 # INITIAL ACTIONS 

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

77 # imagefilecollection) 

78 sof = set_of_files( 

79 log=self.log, 

80 settings=self.settings, 

81 inputFrames=self.inputFrames 

82 ) 

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

84 

85 # VERIFY THE FRAMES ARE THE ONES EXPECTED BY SOXS_order_centres - NO MORE, NO LESS. 

86 # PRINT SUMMARY OF FILES. 

87 print("# VERIFYING INPUT FRAMES") 

88 self.verify_input_frames() 

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

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

91 

92 print("\n# RAW INPUT DARK FRAMES - SUMMARY") 

93 # SORT IMAGE COLLECTION 

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

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

96 

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

98 # EXTENSIONS 

99 self.inputFrames = self.prepare_frames( 

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

101 

102 return None 

103 

104 def verify_input_frames( 

105 self): 

106 """*verify the input frame match those required by the soxs_order_centres recipe* 

107 

108 **Return:** 

109 - ``None`` 

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,ORDERDEF": 

137 raise TypeError( 

138 "Input frames for soxspipe order_centres need to be single pinhole flat-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 order_centres need to be single pinhole flat-lamp on and lamp off frames for NIR" % locals()) 

144 

145 else: 

146 for i in imageTypes: 

147 if i not in ["LAMP,ORDERDEF", "BIAS", "DARK", 'LAMP,DORDERDEF', 'LAMP,QORDERDEF']: 

148 raise TypeError( 

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

150 

151 # LOOK FOR DISP MAP 

152 arm = self.arm 

153 if arm not in self.supplementaryInput or "DISP_MAP" not in self.supplementaryInput[arm]: 

154 raise TypeError( 

155 "Need a first guess dispersion map for %(arm)s - none found with the input files" % locals()) 

156 

157 self.imageType = imageTypes[0] 

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

159 return None 

160 

161 def produce_product( 

162 self): 

163 """*The code to generate the product of the soxs_order_centres recipe* 

164 

165 **Return:** 

166 - ``productPath`` -- the path to the final product 

167 """ 

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

169 

170 arm = self.arm 

171 kw = self.kw 

172 dp = self.detectorParams 

173 

174 productPath = None 

175 

176 master_bias = False 

177 dark = False 

178 orderDef_image = False 

179 

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

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

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

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

184 

185 # UVB/VIS DARK 

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

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 # NIR DARK 

192 add_filters = {kw("DPR_TYPE"): 'LAMP,ORDERDEF', 

193 kw("DPR_TECH"): 'IMAGE'} 

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

195 print(i) 

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

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

198 

199 add_filters = {kw("DPR_TYPE"): 'LAMP,ORDERDEF', 

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

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

202 orderDef_image = CCDData.read(i, hdu=0, unit=u.adu, hdu_uncertainty='ERRS', 

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

204 

205 # UVB - CHECK FOR D2 LAMP FIRST AND IF NOT FOUND USE THE QTH LAMP 

206 add_filters = {kw("DPR_TYPE"): 'LAMP,QORDERDEF', 

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

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

209 orderDef_image = CCDData.read(i, hdu=0, unit=u.adu, hdu_uncertainty='ERRS', 

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

211 

212 add_filters = {kw("DPR_TYPE"): 'LAMP,DORDERDEF', 

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

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

215 orderDef_image = CCDData.read(i, hdu=0, unit=u.adu, hdu_uncertainty='ERRS', 

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

217 

218 self.orderFrame = self.subtract_calibrations( 

219 inputFrame=orderDef_image, master_bias=master_bias, dark=dark) 

220 

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

222 fileDir = self.intermediateRootPath 

223 filepath = self._write( 

224 self.orderFrame, fileDir, filename=False, overwrite=True) 

225 print(f"\nCalibrated single pinhole frame frame saved to {filepath}\n") 

226 

227 # DETECT THE CONTINUUM OF ORDERE CENTRES - RETURN ORDER TABLE FILE PATH 

228 detector = detect_continuum( 

229 log=self.log, 

230 pinholeFlat=self.orderFrame, 

231 dispersion_map=self.supplementaryInput[arm]["DISP_MAP"], 

232 settings=self.settings 

233 ) 

234 productPath = detector.get() 

235 

236 self.clean_up() 

237 

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

239 return productPath 

240 

241 # use the tab-trigger below for new method 

242 # xt-class-method 

243 

244 # Override Method Attributes 

245 # method-override-tmpx