def observation_add_data(self, observation): """ Fill in the metadata for a completed observation """ current_time = Time(self.mjd, format='mjd') observation['clouds'] = self.cloud_data(current_time) observation['airmass'] = 1. / np.cos(np.pi / 2. - observation['alt']) # Seeing fwhm_500 = self.seeing_data(current_time) seeing_dict = self.seeing_model(fwhm_500, observation['airmass']) observation['FWHMeff'] = seeing_dict['fwhmEff'][self.seeing_indx_dict[ observation['filter'][0]]] observation['FWHM_geometric'] = seeing_dict['fwhmGeom'][ self.seeing_indx_dict[observation['filter'][0]]] observation['FWHM_500'] = fwhm_500 observation['night'] = self.night observation['mjd'] = self.mjd hpid = _raDec2Hpid(self.sky_model.nside, observation['RA'], observation['dec']) observation['skybrightness'] = self.sky_model.returnMags( self.mjd, indx=[hpid], extrapolate=True)[observation['filter'][0]] observation['fivesigmadepth'] = m5_flat_sed( observation['filter'][0], observation['skybrightness'], observation['FWHMeff'], observation['exptime'] / observation['nexp'], observation['airmass'], nexp=observation['nexp']) lmst, last = calcLmstLast(self.mjd, self.site.longitude_rad) observation['lmst'] = lmst sun_moon_info = self.almanac.get_sun_moon_positions(self.mjd) observation['sunAlt'] = sun_moon_info['sun_alt'] observation['sunAz'] = sun_moon_info['sun_az'] observation['sunRA'] = sun_moon_info['sun_RA'] observation['sunDec'] = sun_moon_info['sun_dec'] observation['moonAlt'] = sun_moon_info['moon_alt'] observation['moonAz'] = sun_moon_info['moon_az'] observation['moonRA'] = sun_moon_info['moon_RA'] observation['moonDec'] = sun_moon_info['moon_dec'] observation['moonDist'] = _angularSeparation(observation['RA'], observation['dec'], observation['moonRA'], observation['moonDec']) observation['solarElong'] = _angularSeparation(observation['RA'], observation['dec'], observation['sunRA'], observation['sunDec']) observation['moonPhase'] = sun_moon_info['moon_phase'] observation['ID'] = self.obsID_counter self.obsID_counter += 1 return observation
def testRaDecsRad(self): """ Test that the Ra Dec conversions round-trip """ nside = 64 hpids = np.arange(hp.nside2npix(nside)) ra, dec = utils._hpid2RaDec(nside, hpids) hpids_return = utils._raDec2Hpid(nside, ra, dec) np.testing.assert_array_equal(hpids, hpids_return)
def _check_alts(self, indices): """Check the altitudes of potential matches. """ # This is kind of a kludgy low-resolution way to convert ra,dec to alt,az, but should be really fast. # XXX--should I stick the healpixel value on when I set the script? Might be faster. # XXX not sure this really needs to be it's own method hp_ids = _raDec2Hpid(self.nside, self.obs_wanted[indices]['RA'], self.obs_wanted[indices]['dec']) alts = self.extra_features['altaz'].feature['alt'][hp_ids] in_range = np.where((alts < self.max_alt) & (alts > self.min_alt)) indices = indices[in_range] return indices
def screen2hp(nside, mjd, npix=600, height=500.): # generate a screen xx, yy = np.meshgrid(np.arange(-npix, npix, 1), np.arange(-npix, npix, 1), indexing='ij') r = (xx**2+yy**2)**0.5 az = np.arctan2(yy, xx) alt = np.arctan(height/r) ra, dec = stupidFast_altAz2RaDec(alt, az, lat, lon, mjd) # Ah, I can convert these alt,az coords to ra,dec, then there's no problem using an ra,dec cloud map. hpids = _raDec2Hpid(nside, ra, dec) return hpids
def screen2hp(nside, mjd, npix=600, height=500.): # generate a screen xx, yy = np.meshgrid(np.arange(-npix, npix, 1), np.arange(-npix, npix, 1), indexing='ij') r = (xx**2 + yy**2)**0.5 az = np.arctan2(yy, xx) alt = np.arctan(height / r) ra, dec = stupidFast_altAz2RaDec(alt, az, lat, lon, mjd) # Ah, I can convert these alt,az coords to ra,dec, then there's no problem using an ra,dec cloud map. hpids = _raDec2Hpid(nside, ra, dec) return hpids
def _check_mask(self, observation, conditions): """Check that the proposed observation is not currently masked for some reason on the sky map. True if the observation is good to observe False if the proposed observation is masked """ hpid = np.max( _raDec2Hpid(self.nside, observation['RA'], observation['dec'])) skyval = conditions.M5Depth[observation['filter'][0]][hpid] if skyval > 0: return True else: return False
def RaDec2region(ra, dec, nside): SCP_indx, NES_indx, GP_indx, WFD_indx = mutually_exclusive_regions(nside) indices = _raDec2Hpid(nside, np.radians(ra), np.radians(dec)) result = np.empty(np.size(indices), dtype=object) SCP = np.in1d(indices, SCP_indx) NES = np.in1d(indices, NES_indx) GP = np.in1d(indices, GP_indx) WFD = np.in1d(indices, WFD_indx) result[SCP] = 'SCP' result[NES] = 'NES' result[GP] = 'GP' result[WFD] = 'WFD' return result
def RaDec2region(ra, dec, nside): result = np.array(np.size(ra), dtype = str) SCP_indx, NES_indx, GP_indx, WFD_indx = mutually_exclusive_regions(nside) indices = _raDec2Hpid(ra, dec, nside) SCP = np.searchsorted(indices,SCP_indx) NES = np.searchsorted(indices,NES_indx) GP = np.searchsorted(indices,GP_indx) WFD = np.searchsorted(indices,WFD_indx) result[SCP] = 'SCP' result[NES] = 'NES' result[GP] = 'GP' result[WFD] = 'WFD' return result
def __init__(self, basis_functions, basis_weights, extra_features=None, filtername='r', block_size=5, smoothing_kernel=None): super(Simple_greedy_survey_fields_cost, self).__init__(basis_functions=basis_functions, basis_weights=basis_weights, extra_features=extra_features, smoothing_kernel=smoothing_kernel) self.filtername = filtername self.fields = read_fields() self.field_hp = _raDec2Hpid(default_nside, self.fields['RA'], self.fields['dec']) self.block_size = block_size
def __call__(self, observation_list, conditions): """ Parameters ---------- observation_list : list of observations The observations to detail. conditions : lsst.sims.featureScheduler.conditions object Returns ------- List of observations. """ obs_array = np.concatenate(observation_list) hpids = _raDec2Hpid(self.nside, obs_array['RA'], obs_array['dec']) new_expts = np.zeros(obs_array.size, dtype=float) for filtername in np.unique(obs_array['filter']): in_filt = np.where(obs_array['filter'] == filtername) delta_m5 = self.target_m5[filtername] - conditions.M5Depth[filtername][hpids[in_filt]] # We can get NaNs because dithering pushes the center of the pointing into masked regions. nan_indices = np.argwhere(np.isnan(delta_m5)).ravel() for indx in nan_indices: bad_hp = hpids[in_filt][indx] # Note this might fail if we run at higher resolution, then we'd need to look farther for # pixels to interpolate. near_pix = hp.get_all_neighbours(conditions.nside, bad_hp) vals = conditions.M5Depth[filtername][near_pix] if True in np.isfinite(vals): estimate_m5 = np.mean(vals[np.isfinite(vals)]) delta_m5[indx] = self.target_m5[filtername] - estimate_m5 else: raise ValueError('Failed to find a nearby unmasked sky value.') new_expts[in_filt] = conditions.exptime * 10**(delta_m5/1.25) new_expts = np.clip(new_expts, self.min_exp, self.max_exp) # I'm not sure what level of precision we can expect, so let's just limit to seconds new_expts = np.round(new_expts) for i, observation in enumerate(observation_list): observation['exptime'] = new_expts[i] return observation_list
def testBinRad(self): """ Test that healbin returns correct values and valid healpy maps. """ ra = np.zeros(3) dec = np.zeros(3) values = ra * 0. + 1. nside = 128 hpid = utils._raDec2Hpid(nside, ra[0], dec[0]) map1 = utils._healbin(ra, dec, values, nside=nside) self.assertEqual(map1[hpid], 1.) self.assertEqual(hp.maptype(map1), 0) map2 = utils._healbin(ra, dec, values, nside=nside, reduceFunc=np.sum) self.assertEqual(map2[hpid], 3.) self.assertEqual(hp.maptype(map2), 0) map3 = utils._healbin(ra, dec, values, nside=nside, reduceFunc=np.std) self.assertEqual(map3[hpid], 0.) self.assertEqual(hp.maptype(map3), 0)
def _check_observation(self, observation, conditions): delta_t = observation['mjd'] - conditions.mjd log.debug( 'Check_observation: obs_mjd=%.4f (current_mjd=%.4f, delta=%.4f, tol=%.4f)', observation['mjd'], conditions.mjd, delta_t, self.ttol) obs_hp = _raDec2Hpid(self.nside, observation['RA'], observation['dec']) slewtime = conditions.slewtime[obs_hp[0]] in_slew_window = slewtime <= self.max_slew_to_pair or delta_t < 0. in_time_window = np.abs(delta_t) < self.ttol if conditions.current_filter is None: infilt = True else: infilt = conditions.current_filter in self.filt_to_pair is_observable = self._check_mask(observation, conditions) valid = in_time_window & infilt & in_slew_window & is_observable log.debug('Pair - observation: %s ' % observation) log.debug( 'Pair - check[%s]: in_time_window[%s] infilt[%s] in_slew_window[%s] is_observable[%s]' % (valid, in_time_window, infilt, in_slew_window, is_observable)) return (valid, in_time_window, infilt, in_slew_window, is_observable)
def attempt_observe(self, observation_in, indx=None): """ Check an observation, if there is enough time, execute it and return it, otherwise, return None. """ # If we were in a parked position, assume no time lost to slew, settle, filter change observation = observation_in.copy() alt, az = _approx_RaDec2AltAz(np.array([observation['RA']]), np.array([observation['dec']]), self.obs.lat, self.obs.lon, self.mjd) if self.ra is not None: if self.filtername != observation['filter']: ft = self.f_change_time st = 0. else: ft = 0. st = self.slew_time(alt, az) else: st = 0. ft = 0. # Assume we can slew while reading the last exposure (note that slewtime calc gives 2 as a minimum. So this # will not fail for DD fields, etc.) # So, filter change time, slew to target time, expose time, read time rt = (observation['nexp']-1.)*self.readtime shutter_time = self.shutter_time*observation['nexp'] total_time = (ft + st + observation['exptime'] + rt + shutter_time)*sec2days check_result, jump_mjd = self.check_mjd(self.mjd + total_time) if check_result: # XXX--major decision here, should the status be updated after every observation? Or just assume # airmass, seeing, and skybrightness do not change significantly? if self.ra is None: update_status = True else: update_status = False # This should be the start of the exposure. observation['mjd'] = self.mjd + (ft + st)*sec2days self.set_mjd(self.mjd + (ft + st)*sec2days) self.ra = observation['RA'] self.dec = observation['dec'] if update_status: # What's the name for temp variables? status = self.return_status() observation['night'] = self.night # XXX I REALLY HATE THIS! READTIME SHOULD NOT BE LUMPED IN WITH SLEWTIME! # XXX--removing that so I may not be using the same convention as opsim. observation['slewtime'] = ft+st self.filtername = observation['filter'][0] hpid = _raDec2Hpid(self.sky_nside, self.ra, self.dec) observation['skybrightness'] = self.sky.returnMags(observation['mjd'], indx=[hpid], extrapolate=True)[self.filtername] observation['FWHMeff'] = self.status['FWHMeff_%s' % self.filtername][hpid] observation['FWHM_geometric'] = self.status['FWHM_geometric_%s' % self.filtername][hpid] observation['airmass'] = self.status['airmass'][hpid] observation['fivesigmadepth'] = m5_flat_sed(observation['filter'][0], observation['skybrightness'], observation['FWHMeff'], observation['exptime'], observation['airmass']) observation['alt'] = alt observation['az'] = az observation['clouds'] = self.status['clouds'] observation['sunAlt'] = self.status['sunAlt'] observation['moonAlt'] = self.status['moonAlt'] # We had advanced the slew and filter change, so subtract that off and add the total visit time. self.set_mjd(self.mjd + total_time - (ft + st)*sec2days) return observation else: self.mjd = jump_mjd self.night = self.mjd2night(self.mjd) self.ra = None self.dec = None self.status = None self.filtername = None return None
def select_next_target(self): if not self.isnight: return self.nulltarget # Telemetry stream telemetry_stream = self.get_telemetry() self.scheduler.update_conditions(telemetry_stream) winner_target = self.scheduler.request_observation() if winner_target is None: self.log.debug( '[mjd = %.3f]: No target generated by the scheduler...' % telemetry_stream['mjd']) self.scheduler.flush_queue() self.last_winner_target = self.nulltarget.get_copy() return self.last_winner_target self.log.debug('winner target: %s' % winner_target) self.scheduler_winner_target = winner_target hpid = _raDec2Hpid(self.sky_nside, winner_target['RA'][0], winner_target['dec'][0]) propid = winner_target['survey_id'][0] filtername = winner_target['filter'][0] indx = self.proposal_id_dict[propid][0] target = self.generate_target(winner_target[0]) self.target_list[target.fieldid] = {filtername: target} self.science_proposal_list[indx].survey_targets_dict[ target.fieldid] = { filtername: target } target.time = self.time target.ang_rad = self.observatoryModel.radec2altazpa( self.observatoryModel.dateprofile, target.ra_rad, target.dec_rad)[2] self.observatoryModel.current_state.ang_rad = target.ang_rad slewtime, slew_state = self.observatoryModel.get_slew_delay(target) if slewtime > 0.: self.scheduler_winner_target[ 'mjd'] = telemetry_stream['mjd'] + slewtime / 60. / 60. / 24. self.scheduler_winner_target['night'] = self.night self.scheduler_winner_target['slewtime'] = slewtime self.scheduler_winner_target['skybrightness'] = \ self.sky_brightness.returnMags(self.observatoryModel.dateprofile.mjd, indx=[hpid], extrapolate=True)[filtername] self.scheduler_winner_target['FWHMeff'] = telemetry_stream[ 'FWHMeff_%s' % filtername][hpid] self.scheduler_winner_target['FWHM_geometric'] = \ telemetry_stream['FWHM_geometric_%s' % winner_target['filter'][0]][hpid] self.scheduler_winner_target['airmass'] = telemetry_stream[ 'airmass'][hpid] self.scheduler_winner_target['fivesigmadepth'] = m5_flat_sed( filtername, self.scheduler_winner_target['skybrightness'], self.scheduler_winner_target['FWHMeff'], self.scheduler_winner_target['exptime'], self.scheduler_winner_target['airmass']) self.scheduler_winner_target['alt'] = target.alt_rad self.scheduler_winner_target['az'] = target.az_rad self.scheduler_winner_target['rotSkyPos'] = target.ang_rad self.scheduler_winner_target['clouds'] = self.cloud self.scheduler_winner_target['sunAlt'] = telemetry_stream['sunAlt'] self.scheduler_winner_target['moonAlt'] = telemetry_stream[ 'moonAlt'] target.slewtime = slewtime target.airmass = telemetry_stream['airmass'][hpid] target.sky_brightness = self.sky_brightness.returnMags( self.observatoryModel.dateprofile.mjd, indx=[hpid], extrapolate=True)[filtername][0] self.observatoryModel2.set_state(self.observatoryState) self.observatoryState.ang_rad = target.ang_rad self.observatoryModel2.observe(target) target.seeing = self.seeing target.cloud = self.cloud ntime = self.observatoryModel2.current_state.time if ntime < self.sunrise_timestamp: # self.observatoryModel2.update_state(ntime) if self.observatoryModel2.current_state.tracking: target.time = self.time if self.last_winner_target.targetid == target.targetid: self.last_winner_target = self.nulltarget self.targetid -= 1 else: self.last_winner_target = target.get_copy() else: self.log.debug("select_next_target: target rejected %s" % (str(target))) self.log.debug("select_next_target: state rejected %s" % str(self.observatoryModel2.current_state)) self.last_winner_target = self.nulltarget self.targetid -= 1 else: self.last_winner_target = self.nulltarget self.targetid -= 1 else: self.log.debug('Fail state: %i' % slew_state) self.log.debug('Slewtime lower than zero! (slewtime = %f)' % slewtime) self.scheduler.flush_queue() self.targetid -= 1 self.last_winner_target = self.nulltarget self.log.debug(self.last_winner_target) for propid in self.proposal_id_dict.keys(): self.science_proposal_list[self.proposal_id_dict[propid] [0]].winners_list = [] self.science_proposal_list[indx].winners_list = [target.get_copy()] return self.last_winner_target