Source code for lsst.sims.movingObjects.directObs

from __future__ import print_function, division
import numpy as np

from .baseObs import BaseObs

__all__ = ['DirectObs']


[docs]class DirectObs(BaseObs): """ Generate observations of a set of moving objects: exact ephemeris at the times of each observation. First generates observations on a rough grid and looks for observations within a specified tolerance of the actual observations; for the observations which pass this cut, generates a precise ephemeris and checks if the object is within the FOV. Parameters ---------- footPrint: str, opt Specify the footprint for the FOV. Options include "camera", "circle", "rectangle". 'Camera' means use the actual LSST camera footprint (following a rough cut with a circular FOV). Default is circular FOV. rFov : float, opt If footprint is "circular", this is the radius of the fov (in degrees). Default 1.75 degrees. xTol : float, opt If footprint is "rectangular", this is half of the width of the (on-sky) fov in the RA direction (in degrees). Default 5 degrees. (so size of footprint in degrees will be 10 degrees in the RA direction). yTol : float, opt If footprint is "rectangular", this is half of the width of the fov in Declination (in degrees). Default is 3 degrees (so size of footprint in degrees will be 6 degrees in the Dec direction). ephMode: str, opt Mode for ephemeris generation - nbody or 2body. Default is nbody. prelimEphMode: str, opt Mode for preliminary ephemeris generation, if any is done. Default is 2body. ephType: str, opt Type of ephemerides to generate - full or basic. Full includes all values calculated by openorb; Basic includes a more basic set. Default is Basic. (this includes enough information for most standard MAF metrics). ephFile: str or None, opt The name of the planetary ephemerides file to use for ephemeris generation. Default (None) will use the default for PyOrbEphemerides. obsCode: str, opt Observatory code for ephemeris generation. Default is "I11" - Cerro Pachon. obsTimeCol: str, opt Name of the time column in the obsData. Default 'observationStartMJD'. obsTimeScale: str, opt Type of timescale for MJD (TAI or UTC currently). Default TAI. seeingCol: str, opt Name of the seeing column in the obsData. Default 'seeingFwhmGeom'. This should be the geometric/physical seeing as it is used for the trailing loss calculation. visitExpTimeCol: str, opt Name of the visit exposure time column in the obsData. Default 'visitExposureTime'. obsRA: str, opt Name of the RA column in the obsData. Default 'fieldRA'. obsDec: str, opt Name of the Dec column in the obsData. Default 'fieldDec'. obsRotSkyPos: str, opt Name of the Rotator column in the obsData. Default 'rotSkyPos'. obsDegrees: bool, opt Whether the observational data is in degrees or radians. Default True (degrees). outfileName : str, opt The output file name. Default is 'lsst_obs.dat'. obsMetadata : str, opt A string that captures provenance information about the observations. For example: 'kraken_2026, MJD 59853-61677' or 'baseline2018a minus NES' Default ''. tstep: float, opt The time between initial (rough) ephemeris generation points, in days. Default 1 day. roughTol: float, opt The initial rough tolerance value for positions, used as a first cut to identify potential observations (in degrees). Default 10 degrees. """ def __init__(self, footprint='circular', rFov=1.75, xTol=5, yTol=3, ephMode='nbody', prelimEphMode='2body', ephType='basic', obsCode='I11', ephFile=None, obsTimeCol='observationStartMJD', obsTimeScale='TAI', seeingCol='seeingFwhmGeom', visitExpTimeCol='visitExposureTime', obsRA='fieldRA', obsDec='fieldDec', obsRotSkyPos='rotSkyPos', obsDegrees=True, outfileName='lsst_obs.dat', obsMetadata='', tstep=1.0, roughTol=10.0): super().__init__(footprint=footprint, rFov=rFov, xTol=xTol, yTol=yTol, ephMode=ephMode, ephType=ephType, obsCode=obsCode, ephFile=ephFile, obsTimeCol=obsTimeCol, obsTimeScale=obsTimeScale, seeingCol=seeingCol, visitExpTimeCol=visitExpTimeCol, obsRA=obsRA, obsDec=obsDec, obsRotSkyPos=obsRotSkyPos, obsDegrees=obsDegrees, outfileName=outfileName, obsMetadata=obsMetadata) self.tstep = tstep self.roughTol = roughTol if prelimEphMode not in ('2body', 'nbody'): raise ValueError('Ephemeris generation must be 2body or nbody.') self.prelimEphMode = prelimEphMode def _headerMeta(self): # Specific header information for direct obs. self.outfile.write('# direct obs header metadata\n') self.outfile.write('# observation generation via %s\n' % self.__class__.__name__) self.outfile.write('# ephMode %s prelimEphMode %s\n' % (self.ephMode, self.prelimEphMode)) self.outfile.write('# rough tolerance for preliminary match %f\n' % self.roughTol) self.outfile.write('# time step for preliminary match %f\n' % self.tstep)
[docs] def run(self, orbits, obsData): """Find and write the observations of each object to disk. For each object, generate a very rough grid of ephemeris points (typically using 2body integration). Then identify pointings in obsData which are within Parameters ---------- orbits: lsst.sims.movingObjects.Orbits The orbits to generate ephemerides for. obsData : np.recarray The simulated pointing history data. """ # Set the times for the rough ephemeris grid. timeStep = float(self.tstep) timeStart = obsData[self.obsTimeCol].min() - timeStep timeEnd = obsData[self.obsTimeCol].max() + timeStep rough_times = np.arange(timeStart, timeEnd + timeStep / 2.0, timeStep) print('Generating preliminary ephemerides on a grid of %f day timesteps.' % (timeStep)) # For each object, identify observations where the object is within the FOV (or camera footprint). for sso in orbits: objid = sso.orbits['objId'].iloc[0] sedname = sso.orbits['sed_filename'].iloc[0] # Generate ephemerides on the rough grid. ephs = self.generateEphemerides(sso, rough_times, ephMode=self.prelimEphMode, ephType=self.ephType)[0] # Find observations which come within roughTol of the fov. ephsIdxs = np.searchsorted(ephs['time'], obsData[self.obsTimeCol]) roughIdxObs = self._ssoInCircleFov(ephs[ephsIdxs], obsData, self.roughTol) if len(roughIdxObs) > 0: # Generate exact ephemerides for these times. times = obsData[self.obsTimeCol][roughIdxObs] ephs = self.generateEphemerides(sso, times, ephMode=self.ephMode, ephType=self.ephType)[0] # Identify the objects which fell within the specific footprint. idxObs = self.ssoInFov(ephs, obsData[roughIdxObs]) # Write these observations to disk. self.writeObs(objid, ephs[idxObs], obsData[roughIdxObs][idxObs], sedname=sedname)