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

1from builtins import object 

2import numpy as np 

3import os 

4import numbers 

5from lsst.sims.catalogs.db import DBObject 

6from lsst.sims.utils import ObservationMetaData 

7 

8__all__ = ["ObservationMetaDataGenerator"] 

9 

10 

11class ObservationMetaDataGenerator(object): 

12 """ 

13 A class that allows the user to generate instantiations of 

14 `lsst.sims.utils.ObservationMetaData` corresponding to OpSim pointings. 

15 The functionality includes: 

16 - getOpSimRecords : obtain OpSim records matching the intersection of user 

17 specified ranges on each column in the OpSim output database. The 

18 records are in the form of a `numpy.recarray` 

19 - ObservationMetaDataFromPointing : convert an OpSim record for a single 

20 OpSim Pointing to an instance of ObservationMetaData usable by catsim 

21 and PhoSim Instance Catalogs. 

22 - getObservationMetaData : Obtain a list of ObservationMetaData instances 

23 corresponding to OpSim pointings matching the intersection of user 

24 specified ranges on each column in the OpSim output database. 

25 

26 The major method is ObservationMetaDataGenerator.getObservationMetaData() 

27 which accepts bounds on columns of the opsim summary table and returns 

28 a list of ObservationMetaData instantiations that fall within those 

29 bounds. 

30 """ 

31 

32 @property 

33 def table_name(self): 

34 """ 

35 Return the name of the table in the OpSim database that we are querying 

36 """ 

37 return 'Summary' 

38 

39 def _make_opsim_v3_interface(self): 

40 # a dict keyed on the user interface names of the ObservationMetaData columns 

41 # (i.e. the args to getObservationMetaData). Returns a tuple that is the 

42 # (name of data column in OpSim, transformation to go from user interface to OpSim units, 

43 # dtype in OpSim) 

44 # 

45 # Note: this dict will contain entries for every column (except propID) in the OpSim 

46 # summary table, not just those the ObservationMetaDataGenerator is designed to query 

47 # on. The idea is that ObservationMetaData generated by this class will carry around 

48 # records of the values of all of the associated OpSim Summary columns so that users 

49 # can pass those values on to PhoSim/other tools and thier own discretion. 

50 

51 interface_dict = {'obsHistID': ('obsHistID', None, np.int64), 

52 'expDate': ('expDate', None, int), 

53 'fieldRA': ('fieldRA', np.radians, float), 

54 'fieldDec': ('fieldDec', np.radians, float), 

55 'moonRA': ('moonRA', np.radians, float), 

56 'moonDec': ('moonDec', np.radians, float), 

57 'rotSkyPos': ('rotSkyPos', np.radians, float), 

58 'telescopeFilter': 

59 ('filter', lambda x: '\'{}\''.format(x), (str, 1)), 

60 'rawSeeing': ('rawSeeing', None, float), 

61 'sunAlt': ('sunAlt', np.radians, float), 

62 'moonAlt': ('moonAlt', np.radians, float), 

63 'dist2Moon': ('dist2Moon', np.radians, float), 

64 'moonPhase': ('moonPhase', None, float), 

65 'expMJD': ('expMJD', None, float), 

66 'altitude': ('altitude', np.radians, float), 

67 'azimuth': ('azimuth', np.radians, float), 

68 'visitExpTime': ('visitExpTime', None, float), 

69 'airmass': ('airmass', None, float), 

70 'm5': ('fiveSigmaDepth', None, float), 

71 'skyBrightness': ('filtSkyBrightness', None, float), 

72 'sessionID': ('sessionID', None, int), 

73 'fieldID': ('fieldID', None, int), 

74 'night': ('night', None, int), 

75 'visitTime': ('visitTime', None, float), 

76 'finRank': ('finRank', None, float), 

77 'FWHMgeom': ('FWHMgeom', None, float), 

78 # do not include FWHMeff; that is detected by 

79 # self._set_seeing_column() 

80 'transparency': ('transparency', None, float), 

81 'vSkyBright': ('vSkyBright', None, float), 

82 'rotTelPos': ('rotTelPos', None, float), 

83 'lst': ('lst', None, float), 

84 'solarElong': ('solarElong', None, float), 

85 'moonAz': ('moonAz', None, float), 

86 'sunAz': ('sunAz', None, float), 

87 'phaseAngle': ('phaseAngle', None, float), 

88 'rScatter': ('rScatter', None, float), 

89 'mieScatter': ('mieScatter', None, float), 

90 'moonBright': ('moonBright', None, float), 

91 'darkBright': ('darkBright', None, float), 

92 'wind': ('wind', None, float), 

93 'humidity': ('humidity', None, float), 

94 'slewDist': ('slewDist', None, float), 

95 'slewTime': ('slewTime', None, float), 

96 'ditheredRA': ('ditheredRA', None, float), 

97 'ditheredDec': ('ditheredDec', None, float)} 

98 

99 return interface_dict 

100 

101 def _make_opsim_v4_interface(self): 

102 interface_dict = {'obsHistID': ('observationId', None, np.int64), 

103 'fieldRA': ('fieldRA', None, float), 

104 'fieldDec': ('fieldDec', None, float), 

105 'moonRA': ('moonRA', None, float), 

106 'moonDec': ('moonDec', None, float), 

107 'rotSkyPos': ('rotSkyPos', None, float), 

108 'telescopeFilter': 

109 ('filter', lambda x: '\'{}\''.format(x), (str, 1)), 

110 'sunAlt': ('sunAlt', None, float), 

111 'moonAlt': ('moonAlt', None, float), 

112 'moonPhase': ('moonPhase', None, float), 

113 'expMJD': ('observationStartMJD', None, float), 

114 'altitude': ('altitude', None, float), 

115 'azimuth': ('azimuth', None, float), 

116 'visitExpTime': ('visitExposureTime', None, float), 

117 'airmass': ('airmass', None, float), 

118 'm5': ('fiveSigmaDepth', None, float), 

119 'skyBrightness': ('skyBrightness', None, float), 

120 'fieldID': ('fieldId', None, int), 

121 'night': ('night', None, int), 

122 'visitTime': ('visitTime', None, float), 

123 'FWHMgeom': ('seeingFWHMgeom', None, float), 

124 # do not include FWHMeff; that is detected by 

125 # self._set_seeing_column() 

126 'rotTelPos': ('rotTelPos', None, float), 

127 'lst': ('observationStartLST', None, float), 

128 'solarElong': ('solarElong', None, float), 

129 'moonAz': ('moonAz', None, float), 

130 'sunAz': ('sunAz', None, float), 

131 'slewDist': ('slewDistance', None, float), 

132 'slewTime': ('slewTime', None, float), 

133 'note': ('note', None, str)} 

134 

135 return interface_dict 

136 

137 def _set_seeing_column(self, input_summary_columns): 

138 """ 

139 input_summary_columns is a list of columns in the OpSim database schema 

140 

141 This method sets the member variable self._seeing_column to a string 

142 denoting the name of the seeing column in the OpSimDatabase. It also 

143 sets self.user_interface_to_opsim['seeing'] to the correct value. 

144 """ 

145 

146 if 'FWHMeff' in input_summary_columns: 

147 self._seeing_column = 'FWHMeff' 

148 elif 'seeingFwhmEff' in input_summary_columns: 

149 self._seeing_column = 'seeingFwhmEff' 

150 else: 

151 self._seeing_column = 'finSeeing' 

152 

153 self.user_interface_to_opsim['seeing'] = (self._seeing_column, None, float) 

154 

155 @property 

156 def opsim_version(self): 

157 return self._opsim_version 

158 

159 @property 

160 def user_interface_to_opsim(self): 

161 if not hasattr(self, '_user_interface_to_opsim'): 

162 if self.opsim_version == 3: 

163 self._user_interface_to_opsim = self._make_opsim_v3_interface() 

164 elif self.opsim_version == 4: 

165 self._user_interface_to_opsim = self._make_opsim_v4_interface() 

166 else: 

167 raise RuntimeError("Unsure how to handle opsim_version ",self.opsim_version) 

168 return self._user_interface_to_opsim 

169 

170 @property 

171 def table_name(self): 

172 if self.opsim_version == 3: 

173 return 'Summary' 

174 elif self.opsim_version == 4: 

175 return 'SummaryAllProps' 

176 raise RuntimeError("Unsure how to handle opsim_version ",self.opsim_version) 

177 

178 def __init__(self, database=None, driver='sqlite', host=None, port=None): 

179 """ 

180 Constructor for the class 

181 

182 Parameters 

183 ---------- 

184 database : string 

185 absolute path to the output of the OpSim database 

186 driver : string, optional, defaults to 'sqlite' 

187 driver/dialect for the SQL database 

188 host : hostName, optional, defaults to None, 

189 hostName, None is good for a local database 

190 port : hostName, optional, defaults to None, 

191 port, None is good for a local database 

192 

193 Returns 

194 ------ 

195 Instance of the ObserverMetaDataGenerator class 

196 

197 ..notes : For testing purposes a small OpSim database is available at 

198 `os.path.join(getPackageDir('sims_data'), 'OpSimData/opsimblitz1_1133_sqlite.db')` 

199 """ 

200 self._opsim_version = None 

201 self.driver = driver 

202 self.host = host 

203 self.port = port 

204 self.database = database 

205 self._seeing_column = 'FWHMeff' 

206 

207 if self.database is None: 

208 return 

209 

210 if not os.path.isfile(self.database): 

211 raise RuntimeError('%s is not a file' % self.database) 

212 

213 self.opsimdb = DBObject(driver=self.driver, database=self.database, 

214 host=self.host, port=self.port) 

215 

216 # 27 January 2016 

217 # Detect whether the OpSim db you are connecting to uses 'finSeeing' 

218 # as its seeing column (deprecated), or FWHMeff, which is the modern 

219 # standard 

220 

221 list_of_tables = self.opsimdb.get_table_names() 

222 if 'Summary' in list_of_tables: 

223 self._opsim_version = 3 

224 else: 

225 self._opsim_version = 4 

226 

227 self._summary_columns = self.opsimdb.get_column_names(self.table_name) 

228 self._set_seeing_column(self._summary_columns) 

229 

230 # Set up self.dtype containg the dtype of the recarray we expect back from the SQL query. 

231 # Also setup baseQuery which is just the SELECT clause of the SQL query 

232 # 

233 # self.active_columns will be a list containing the subset of OpSim database columns 

234 # (specified in self.user_interface_to_opsim) that actually exist in this opsim database 

235 dtypeList = [] 

236 self.baseQuery = 'SELECT' 

237 self.active_columns = [] 

238 

239 self._queried_columns = [] # This will be a list of all of the 

240 # OpSim columns queried 

241 # Note: here we will refer to the 

242 # columns by their names in OpSim 

243 

244 for column in self.user_interface_to_opsim: 

245 rec = self.user_interface_to_opsim[column] 

246 if rec[0] in self._summary_columns: 

247 self.active_columns.append(column) 

248 dtypeList.append((rec[0], rec[2])) 

249 if self.baseQuery != 'SELECT': 

250 self.baseQuery += ',' 

251 self.baseQuery += ' ' + rec[0] 

252 self._queried_columns.append(rec[0]) 

253 

254 # Now loop over self._summary_columns, adding any columns 

255 # to the query that have not already been included therein. 

256 # Since we do not have explicit information about the 

257 # data types of these columns, we will assume they are floats. 

258 for column in self._summary_columns: 

259 if column not in self._queried_columns: 

260 self.baseQuery += ', ' + column 

261 dtypeList.append((column, float)) 

262 

263 self.dtype = np.dtype(dtypeList) 

264 

265 def getOpSimRecords(self, obsHistID=None, expDate=None, night=None, fieldRA=None, 

266 fieldDec=None, moonRA=None, moonDec=None, 

267 rotSkyPos=None, telescopeFilter=None, rawSeeing=None, 

268 seeing=None, sunAlt=None, moonAlt=None, dist2Moon=None, 

269 moonPhase=None, expMJD=None, altitude=None, 

270 azimuth=None, visitExpTime=None, airmass=None, 

271 skyBrightness=None, m5=None, boundType='circle', 

272 boundLength=1.75, limit=None): 

273 """ 

274 This method will query the summary table in the `self.opsimdb` database 

275 according to constraints specified in the input ranges and return a 

276 `numpy.recarray` containing the records that match those constraints. If limit 

277 is used, the first N records will be returned in the list. 

278 

279 Parameters 

280 ---------- 

281 obsHistID, expDate, night, fieldRA, fieldDec, moonRa, moonDec, rotSkyPos, 

282 telescopeFilter, rawSeeing, seeing, sunAlt, moonAlt, dist2Moon, 

283 moonPhase, expMJD, altitude, azimuth, visitExpTime, airmass, 

284 skyBrightness, m5 : tuples of length 2, optional, defaults to None 

285 each of these variables represent a single column (perhaps through 

286 an alias) in the OpSim database, and potentially in a different unit. 

287 if not None, the variable self.columnMapping is used to constrain 

288 the corresponding column in the OpSim database to the ranges (inclusive) 

289 specified in the tuples, after a unit transformation if necessary. 

290 

291 The ranges must be specified in the tuple in degrees for all angles in this 

292 (moonRa, moonDec, rotSkyPos, sunAlt, moonAlt, dist2Moon, altitude, 

293 azimuth). The times in (expMJD, are in units of MJD). visitExpTime has 

294 units of seconds since the start of the survey. moonPhase is a number 

295 from 0., to 100. 

296 boundType : `sims.utils.ObservationMetaData.boundType`, optional, defaults to 'circle' 

297 {'circle', 'box'} denoting the shape of the pointing. Further 

298 documentation `sims.catalogs.generation.db.spatialBounds.py`` 

299 boundLength : float, optional, defaults to 0.1 

300 sets `sims.utils.ObservationMetaData.boundLenght` 

301 limit : integer, optional, defaults to None 

302 if not None, denotes max number of records returned by the query 

303 

304 Returns 

305 ------- 

306 `numpy.recarray` with OpSim records. The column names may be obtained as 

307 res.dtype.names 

308 

309 .. notes:: The `limit` argument should only be used if a small example 

310 is required. The angle ranges in the argument should be specified in degrees. 

311 """ 

312 

313 self._set_seeing_column(self._summary_columns) 

314 

315 query = self.baseQuery + ' FROM %s' % self.table_name 

316 

317 nConstraints = 0 # the number of constraints in this query 

318 

319 for column in self.user_interface_to_opsim: 

320 transform = self.user_interface_to_opsim[column] 

321 

322 # this try/except block is because there will be columns in the OpSim Summary 

323 # table (and thus in self.user_interface_to_opsim) which the 

324 # ObservationMetaDataGenerator is not designed to query on 

325 try: 

326 value = eval(column) 

327 except: 

328 value = None 

329 

330 if value is not None: 

331 if column not in self.active_columns: 

332 raise RuntimeError("You have asked ObservationMetaDataGenerator to SELECT pointings on " 

333 "%s; that column does not exist in your OpSim database" % column) 

334 if nConstraints > 0: 

335 query += ' AND' 

336 else: 

337 query += ' WHERE ' 

338 

339 if isinstance(value, tuple): 

340 if len(value) > 2: 

341 raise RuntimeError('Cannot pass a tuple longer than 2 elements ' + 

342 'to getObservationMetaData: %s is len %d' 

343 % (column, len(value))) 

344 

345 # perform any necessary coordinate transformations 

346 if transform[1] is not None: 

347 vmin = transform[1](value[0]) 

348 vmax = transform[1](value[1]) 

349 else: 

350 vmin = value[0] 

351 vmax = value[1] 

352 

353 query += ' %s >= %s AND %s <= %s' % \ 

354 (transform[0], vmin, transform[0], vmax) 

355 else: 

356 # perform any necessary coordinate transformations 

357 if transform[1] is not None: 

358 vv = transform[1](value) 

359 else: 

360 vv = value 

361 

362 if isinstance(vv, numbers.Number): 

363 tol = np.abs(vv)*1.0e-10 

364 if tol == 0.0: 

365 tol = 1.0e-10 

366 query += ' %s < %.12e AND %s > %.12e' % (transform[0], 

367 vv+tol, 

368 transform[0], 

369 vv-tol) 

370 else: 

371 query += ' %s == %s' % (transform[0], vv) 

372 

373 nConstraints += 1 

374 

375 mjd_name = self.user_interface_to_opsim['expMJD'][0] 

376 query += ' GROUP BY %s ORDER BY %s' % (mjd_name, mjd_name) 

377 

378 if limit is not None: 

379 query += ' LIMIT %d' % limit 

380 

381 if nConstraints == 0 and limit is None: 

382 raise RuntimeError('You did not specify any contraints on your query;' + 

383 ' you will just return ObservationMetaData for all poitnings') 

384 

385 results = self.opsimdb.execute_arbitrary(query, dtype=self.dtype) 

386 return results 

387 

388 def ObservationMetaDataFromPointing(self, OpSimPointingRecord, OpSimColumns=None, 

389 boundLength=1.75, boundType='circle'): 

390 """ 

391 Return instance of ObservationMetaData for an OpSim Pointing record 

392 from OpSim. 

393 

394 Parameters 

395 ---------- 

396 OpSimPointingRecord : Dictionary, mandatory 

397 Dictionary of values with keys corresponding to certain columns of 

398 the Summary table in the OpSim database. The minimal list of keys 

399 required for catsim to work is 'fiveSigmaDepth', 

400 'filtSkyBrightness', and at least one of ('finSeeing', 'FWHMeff'). 

401 More keys defined in columnMap may be necessary for PhoSim to work. 

402 OpSimColumns : tuple of strings, optional, defaults to None 

403 The columns corresponding to the OpSim records. If None, attempts 

404 to obtain these from the OpSimRecord as OpSimRecord.dtype.names 

405 boundType : {'circle', 'box'}, optional, defaults to 'circle' 

406 Shape of the observation 

407 boundLength : scalar float, optional, defaults to 1.75 

408 'characteristic size' of observation field, in units of degrees. 

409 For boundType='circle', this is a radius, for boundType='box', this 

410 is a size of the box 

411 """ 

412 

413 pointing = OpSimPointingRecord 

414 pointing_column_names = pointing.dtype.names 

415 # Decide what is the name of the column in the OpSim database 

416 # corresponding to the Seeing. For older OpSim outputs, this is 

417 # 'finSeeing'. For later OpSim outputs this is 'FWHMeff' 

418 if OpSimColumns is None: 

419 OpSimColumns = pointing_column_names 

420 

421 self._set_seeing_column(OpSimColumns) 

422 

423 # get the names of the columns that contain the minimal schema 

424 # for an ObservationMetaData 

425 mjd_name = self.user_interface_to_opsim['expMJD'][0] 

426 ra_name = self.user_interface_to_opsim['fieldRA'][0] 

427 dec_name = self.user_interface_to_opsim['fieldDec'][0] 

428 filter_name = self.user_interface_to_opsim['telescopeFilter'][0] 

429 

430 # check to see if angles are in degrees or radians 

431 if self.user_interface_to_opsim['fieldRA'][1] is None: 

432 in_degrees = True 

433 else: 

434 in_degrees = False 

435 

436 # check to make sure the OpSim pointings being supplied contain 

437 # the minimum required information 

438 

439 for required_column in (ra_name, dec_name, mjd_name, filter_name): 

440 if required_column not in OpSimColumns: 

441 raise RuntimeError("ObservationMetaDataGenerator requires that the database of " 

442 "pointings include data for:\nfieldRA" 

443 "\nfieldDec\nexpMJD\nfilter") 

444 

445 # construct a raw dict of all of the OpSim columns associated with this pointing 

446 raw_dict = dict([(col, pointing[col]) for col in pointing_column_names]) 

447 raw_dict['opsim_version'] = self.opsim_version 

448 

449 if in_degrees: 

450 ra_val = pointing[ra_name] 

451 dec_val = pointing[dec_name] 

452 else: 

453 ra_val = np.degrees(pointing[ra_name]) 

454 dec_val = np.degrees(pointing[dec_name]) 

455 mjd_val = pointing[mjd_name] 

456 filter_val = pointing[filter_name] 

457 

458 obs = ObservationMetaData(pointingRA=ra_val, 

459 pointingDec=dec_val, 

460 mjd=mjd_val, 

461 bandpassName=filter_val, 

462 boundType=boundType, 

463 boundLength=boundLength) 

464 

465 m5_name = self.user_interface_to_opsim['m5'][0] 

466 rotSky_name = self.user_interface_to_opsim['rotSkyPos'][0] 

467 

468 if m5_name in pointing_column_names: 

469 obs.m5 = pointing[m5_name] 

470 if 'filtSkyBrightness' in pointing_column_names: 

471 obs.skyBrightness = pointing['filtSkyBrightness'] 

472 if self._seeing_column in pointing_column_names: 

473 obs.seeing = pointing[self._seeing_column] 

474 if rotSky_name in pointing_column_names: 

475 if in_degrees: 

476 obs.rotSkyPos = pointing[rotSky_name] 

477 else: 

478 obs.rotSkyPos = np.degrees(pointing[rotSky_name]) 

479 

480 obs.OpsimMetaData = raw_dict 

481 

482 return obs 

483 

484 def ObservationMetaDataFromPointingArray(self, OpSimPointingRecords, 

485 OpSimColumns=None, 

486 boundLength=1.75, 

487 boundType='circle'): 

488 """ 

489 Static method to get a list of instances of ObservationMetaData 

490 corresponding to the records in `numpy.recarray`, where it uses 

491 the dtypes of the recArray for ObservationMetaData attributes that 

492 require the dtype. 

493 

494 Parameters 

495 ---------- 

496 OpSimPointingRecords : `numpy.recarray` of OpSim Records 

497 OpSimColumns : a tuple of strings, optional, defaults to None 

498 tuple of column Names of the data in the `numpy.recarray`. If 

499 None, these names are extracted from the recarray. 

500 boundType : {'circle' or 'box'} 

501 denotes the shape of the pointing 

502 boundLength : float, optional, defaults to 1.75 

503 the bound length of the Pointing in units of degrees. For boundType 

504 'box', this is the length of the side of the square box. For boundType 

505 'circle' this is the radius. 

506 """ 

507 

508 if OpSimColumns is None: 

509 OpSimColumns = OpSimPointingRecords.dtype.names 

510 

511 if self.opsim_version is None: 

512 if 'obsHistID' in OpSimColumns: 

513 self._opsim_version = 3 

514 elif 'observationId' in OpSimColumns: 

515 self._opsim_version = 4 

516 else: 

517 raise RuntimeError("Unable to determine which OpSim version your " 

518 "OpSimPointingRecords correspond to; make sure " 

519 "obsHistID (v3) or observationId (v4) are in the " 

520 "records.") 

521 

522 out = list(self.ObservationMetaDataFromPointing(OpSimPointingRecord, 

523 OpSimColumns=OpSimColumns, 

524 boundLength=boundLength, 

525 boundType=boundType) 

526 for OpSimPointingRecord in OpSimPointingRecords) 

527 

528 return out 

529 

530 def getObservationMetaData(self, obsHistID=None, expDate=None, night=None, fieldRA=None, fieldDec=None, 

531 moonRA=None, moonDec=None, rotSkyPos=None, telescopeFilter=None, 

532 rawSeeing=None, seeing=None, sunAlt=None, moonAlt=None, dist2Moon=None, 

533 moonPhase=None, expMJD=None, altitude=None, azimuth=None, 

534 visitExpTime=None, airmass=None, skyBrightness=None, 

535 m5=None, boundType='circle', boundLength=1.75, limit=None): 

536 

537 """ 

538 This method will query the OpSim database summary table according to user-specified 

539 constraints and return a list of of ObservationMetaData instantiations consistent 

540 with those constraints. 

541 

542 @param [in] limit is an integer denoting the maximum number of ObservationMetaData to 

543 be returned 

544 

545 @param [in] boundType is the boundType of the ObservationMetaData to be returned 

546 (see documentation in sims_catalogs_generation/../db/spatialBounds.py for more 

547 details) 

548 

549 @param [in] boundLength is the boundLength of the ObservationMetaData to be 

550 returned (in degrees; see documentation in 

551 sims_catalogs_generation/../db/spatialBounds.py for more details) 

552 

553 All other input parameters are constraints to be placed on the SQL query of the 

554 opsim output db. These contraints can either be tuples of the form (min, max) 

555 or an exact value the user wants returned. Note: min and max are inclusive 

556 bounds. 

557 

558 Parameters that can be constrained are: 

559 

560 @param [in] fieldRA in degrees 

561 @param [in] fieldDec in degrees 

562 @param [in] altitude in degrees 

563 @param [in] azimuth in degrees 

564 

565 @param [in] moonRA in degrees 

566 @param [in] moonDec in degrees 

567 @param [in] moonAlt in degrees 

568 @param [in] moonPhase (a value from 1 to 100 indicating how much of the moon is illuminated) 

569 @param [in] dist2Moon the distance between the telescope pointing and the moon in degrees 

570 

571 @param [in] sunAlt in degrees 

572 

573 @param [in[ rotSkyPos (the angle of the sky with respect to the camera coordinate system) in degrees 

574 @param [in] telescopeFilter a string that is one of u,g,r,i,z,y 

575 

576 @param [in] airmass 

577 @param [in] rawSeeing (this is an idealized seeing at zenith at 500nm in arcseconds) 

578 @param [in] seeing (this is the OpSim column 'FWHMeff' or 'finSeeing' [deprecated] in arcseconds) 

579 

580 @param [in] visitExpTime the exposure time in seconds 

581 @param [in] obsHistID the integer used by OpSim to label pointings 

582 @param [in] expDate is the date of the exposure (units????) 

583 @param [in] expMJD is the MJD of the exposure 

584 @param [in] night is the night (an int starting at zero) on which the observation took place 

585 @param [in] m5 is the five sigma depth of the observation 

586 @param [in] skyBrightness 

587 """ 

588 

589 OpSimPointingRecords = self.getOpSimRecords(obsHistID=obsHistID, 

590 expDate=expDate, 

591 night=night, 

592 fieldRA=fieldRA, 

593 fieldDec=fieldDec, 

594 moonRA=moonRA, 

595 moonDec=moonDec, 

596 rotSkyPos=rotSkyPos, 

597 telescopeFilter=telescopeFilter, 

598 rawSeeing=rawSeeing, 

599 seeing=seeing, 

600 sunAlt=sunAlt, 

601 moonAlt=moonAlt, 

602 dist2Moon=dist2Moon, 

603 moonPhase=moonPhase, 

604 expMJD=expMJD, 

605 altitude=altitude, 

606 azimuth=azimuth, 

607 visitExpTime=visitExpTime, 

608 airmass=airmass, 

609 skyBrightness=skyBrightness, 

610 m5=m5, boundType=boundType, 

611 boundLength=boundLength, 

612 limit=limit) 

613 

614 output = self.ObservationMetaDataFromPointingArray(OpSimPointingRecords, 

615 OpSimColumns=None, 

616 boundType=boundType, 

617 boundLength=boundLength) 

618 return output