Coverage for python/lsst/obs/base/makeRawVisitInfo.py : 78%

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
# # LSST Data Management System # Copyright 2016 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see <http://www.lsstcorp.org/LegalNotices/>. #
# have these read at need, to avoid unexpected errors later
"""Base class functor to make a VisitInfo from the FITS header of a raw image.
A subclass will be wanted for each camera. Subclasses should override:
- `setArgDict`, The override can call the base implementation, which simply sets exposure time and date of observation - `getDateAvg`
The design philosophy is to make a best effort and log warnings of problems, rather than raising exceptions, in order to extract as much VisitInfo information as possible from a messy FITS header without the user needing to add a lot of error handling.
However, the methods that transform units are less forgiving; they assume the user provides proper data types, since type errors in arguments to those are almost certainly due to coding mistakes.
Parameters ---------- log : `lsst.log.Log` or None Logger to use for messages. (None to use ``Log.getLogger("MakeRawVisitInfo")``). """
"""Construct a VisitInfo and strip associated data from the metadata.
Parameters ---------- md : `lsst.daf.base.PropertyList` or `lsst.daf.base.PropertySet` Metadata to pull from. Items that are used are stripped from the metadata (except TIMESYS, because it may apply to other keywords). exposureId : `int` exposure ID
Notes ----- The basic implementation sets `date` and `exposureTime` using typical values found in FITS files and logs a warning if neither can be set. """ self.log.warn("argDict[{}] is None; stripping".format(key, argDict[key])) del argDict[key]
"""Fill an argument dict with arguments for VisitInfo and pop associated metadata
Subclasses are expected to override this method, though the override may wish to call this default implementation, which:
- sets exposureTime from "EXPTIME" - sets date by calling getDateAvg
Parameters ---------- md : `lsst.daf.base.PropertyList` or `PropertySet` Metadata to pull from. Items that are used are stripped from the metadata (except TIMESYS, because it may apply to other keywords). argdict : `dict` dict of arguments
Notes ----- Subclasses should expand this or replace it. """
"""Return date at the middle of the exposure.
Parameters ---------- md : `lsst.daf.base.PropertyList` or `PropertySet` Metadata to pull from. Items that are used are stripped from the metadata (except TIMESYS, because it may apply to other keywords). exposureTime : `float` Exposure time (sec)
Notes ----- Subclasses must override. Here is a typical implementation::
dateObs = self.popIsoDate(md, "DATE-OBS") return self.offsetDate(dateObs, 0.5*exposureTime) """ raise NotImplementedError()
"""Get the darkTime from the DARKTIME keyword, else expTime, else NaN,
If dark time is available then subclasses should call this method by putting the following in their `__init__` method::
argDict['darkTime'] = self.getDarkTime(argDict)
Parameters ---------- argdict : `dict` Dict of arguments.
Returns ------- `float` Dark time, as inferred from the metadata. """ darkTime = argDict.get("darkTime", NaN) if np.isfinite(darkTime): return darkTime
self.log.info("darkTime is NaN/Inf; using exposureTime") exposureTime = argDict.get("exposureTime", NaN) if not np.isfinite(exposureTime): raise RuntimeError("Tried to substitute exposureTime for darkTime but it is not available")
return exposureTime
"""Return a date offset by a specified number of seconds.
date : `lsst.daf.base.DateTime` Date baseline to offset from. offsetSec : `float` Offset, in seconds.
Returns ------- `lsst.daf.base.DateTime` The offset date. """
"""Remove an item of metadata and return the value.
Log a warning if the key is not found.
Parameters ---------- md : `lsst.daf.base.PropertyList` or `PropertySet` Metadata to pull `key` from and remove. key : `str` Metadata key to extract. default : `object` Value to return if key not found.
Returns ------- `object` The value of the specified key, using whatever type md.getScalar(key) returns. """ except Exception as e: # this should never happen, but is a last ditch attempt to avoid exceptions self.log.warn("Could not read key=\"{}\" in metadata: {}" % (key, e)) return default
"""Pop a float with a default of NaN.
Parameters ---------- md : `lsst.daf.base.PropertyList` or `PropertySet` Metadata to pull `key` from and remove. key : `str` Key to read and remove from md.
Returns ------- `float` Value of the requested key as a float; float("nan") if the key is not found. """
"""Pop an lsst.afw.geom.Angle, whose metadata is in the specified units, with a default of Nan
The angle may be specified as a float or sexagesimal string with 1-3 fields.
Parameters ---------- md : `lsst.daf.base.PropertyList` or `PropertySet` Metadata to pull `key` from and remove. key : `str` Key to read and remove from md.
Returns ------- `lsst.afw.geom.Angle` Value of the requested key as an angle; Angle(NaN) if the key is not found. """
"""Pop a FITS ISO date as an lsst.daf.base.DateTime
Parameters ---------- md : `lsst.daf.base.PropertyList` or `PropertySet` Metadata to pull `key` from and remove. key : `str` Date key to read and remove from md. timesys : `str` Time system as a string (not case sensitive), e.g. "UTC" or None; if None then look for TIMESYS (but do NOT pop it, since it may be used for more than one date) and if not found, use UTC.
Returns ------- `lsst.daf.base.DateTime` Value of the requested date; `DateTime()` if the key is not found. """ # DateTime uses nanosecond resolution, regardless of the resolution of the original date # isot is ISO8601 format with "T" separating date and time and no time zone
"""Get a FITS MJD date as an ``lsst.daf.base.DateTime``.
Parameters ---------- md : `lsst.daf.base.PropertyList` or `PropertySet` Metadata to pull `key` from and remove. key : `str` Date key to read and remove from md. timesys : `str` Time system as a string (not case sensitive), e.g. "UTC" or None; if None then look for TIMESYS (but do NOT pop it, since it may be used for more than one date) and if not found, use UTC.
Returns ------- `lsst.daf.base.DateTime` Value of the requested date; `DateTime()` if the key is not found. """ # DateTime uses nanosecond resolution, regardless of the resolution of the original date # isot is ISO8601 format with "T" separating date and time and no time zone
def eraFromLstAndLongitude(lst, longitude): """ Return an approximate Earth Rotation Angle (afw:Angle) computed from local sidereal time and longitude (both as afw:Angle; Longitude shares the afw:Observatory covention: positive values are E of Greenwich).
NOTE: if we properly compute ERA via UT1 a la DM-8053, we should remove this method. """
def altitudeFromZenithDistance(zd): """Convert zenith distance to altitude (lsst.afw.geom.Angle)"""
def centigradeFromKelvin(tempK): """Convert temperature from Kelvin to Centigrade"""
def pascalFromMBar(mbar): """Convert pressure from millibars to Pascals """ return mbar*PascalPerMillibar
def pascalFromMmHg(mmHg): """Convert pressure from mm Hg to Pascals
Notes ----- Could use the following, but astropy.units.cds is not fully compatible with Python 2 as of astropy 1.2.1 (see https://github.com/astropy/astropy/issues/5350#issuecomment-248612824): astropy.units.cds.mmHg.to(astropy.units.pascal, mmHg) """
def pascalFromTorr(torr): """Convert pressure from torr to Pascals """ return torr*PascalPerTorr
"""Return the value if it is not NaN and within min/max, otherwise return defaultValue.
Parameters ---------- value : `float` metadata value returned by popItem, popFloat, or popAngle defaultValue : `float`` default value to use if the metadata value is invalid minimum : `float` Minimum possible valid value, optional maximum : `float` Maximum possible valid value, optional
Returns ------- `float` The "validated" value. """ if np.isnan(value): retVal = defaultValue else: if minimum is not None and value < minimum: retVal = defaultValue elif maximum is not None and value > maximum: retVal = defaultValue else: retVal = value return retVal |