LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Private Member Functions | List of all members
lsst.daf.butlerUtils.cameraMapper.CameraMapper Class Reference
Inheritance diagram for lsst.daf.butlerUtils.cameraMapper.CameraMapper:
lsst.daf.persistence.mapper.Mapper

Public Member Functions

def __init__
 
def backup
 
def keys
 
def getKeys
 
def getDefaultLevel
 
def getDefaultSubLevel
 
def getCameraName
 
def getPackageName
 
def map_camera
 
def bypass_camera
 
def map_defects
 
def bypass_defects
 
def std_raw
 
def map_skypolicy
 
def std_skypolicy
 
- Public Member Functions inherited from lsst.daf.persistence.mapper.Mapper
def __new__
 
def __init__
 
def __getstate__
 
def __setstate__
 
def keys
 
def queryMetadata
 
def getDatasetTypes
 
def map
 
def canStandardize
 
def standardize
 
def validate
 
def backup
 

Static Public Member Functions

def getShortCcdName
 

Public Attributes

 log
 
 levels
 
 defaultLevel
 
 defaultSubLevels
 
 root
 
 registry
 
 keyDict
 
 mappings
 
 cameraDataLocation
 
 camera
 
 defectRegistry
 
 defectPath
 
 filters
 
 skypolicy
 

Static Public Attributes

 packageName = None
 

Private Member Functions

def _parentSearch
 
def _getCcdKeyVal
 Utility functions. More...
 
def _setupRegistry
 
def _transformId
 
def _mapActualToPath
 
def _extractDetectorName
 
def _extractAmpId
 
def _setAmpDetector
 
def _setCcdDetector
 
def _setFilter
 
def _setTimes
 
def _standardizeExposure
 
def _defectLookup
 
def _makeCamera
 

Detailed Description

CameraMapper is a base class for mappers that handle images from a
camera and products derived from them.  This provides an abstraction layer
between the data on disk and the code.

Public methods: keys, queryMetadata, getDatasetTypes, map,
canStandardize, standardize

Mappers for specific data sources (e.g., CFHT Megacam, LSST
simulations, etc.) should inherit this class.

The CameraMapper manages datasets within a "root" directory.  It can also
be given an "outputRoot".  If so, the input root is linked into the
outputRoot directory using a symlink named "_parent"; writes go into the
outputRoot while reads can come from either the root or outputRoot.  As
outputRoots are used as inputs for further processing, the chain of
_parent links allows any dataset to be retrieved.  Note that writing to a
dataset present in the input root will hide the existing dataset but not
overwrite it.  See #2160 for design discussion.

A camera is assumed to consist of one or more rafts, each composed of
multiple CCDs.  Each CCD is in turn composed of one or more amplifiers
(amps).  A camera is also assumed to have a camera geometry description
(CameraGeom object) as a policy file, a filter description (Filter class
static configuration) as another policy file, and an optional defects
description directory.

Information from the camera geometry and defects are inserted into all
Exposure objects returned.

The mapper uses one or two registries to retrieve metadata about the
images.  The first is a registry of all raw exposures.  This must contain
the time of the observation.  One or more tables (or the equivalent)
within the registry are used to look up data identifier components that
are not specified by the user (e.g. filter) and to return results for
metadata queries.  The second is an optional registry of all calibration
data.  This should contain validity start and end entries for each
calibration dataset in the same timescale as the observation time.

The following method must be provided by the subclass:

_extractDetectorName(self, dataId): returns the detector name for a CCD
(e.g., "CFHT 21", "R:1,2 S:3,4") as used in the AFW CameraGeom class given
a dataset identifier referring to that CCD or a subcomponent of it.

Other methods that the subclass may wish to override include:

_transformId(self, dataId): transformation of a data identifier
from colloquial usage (e.g., "ccdname") to proper/actual usage (e.g., "ccd"),
including making suitable for path expansion (e.g. removing commas).
The default implementation does nothing.  Note that this
method should not modify its input parameter.

getShortCcdName(self, ccdName): a static method that returns a shortened name
suitable for use as a filename. The default version converts spaces to underscores.

_getCcdKeyVal(self, dataId): return a CCD key and value
by which to look up defects in the defects registry.
The default value returns ("ccd", detector name)

_mapActualToPath(self, template, actualId): convert a template path to an
actual path, using the actual dataset identifier.

The mapper's behaviors are largely specified by the policy file.
See the MapperDictionary.paf for descriptions of the available items.

The 'exposures', 'calibrations', and 'datasets' subpolicies configure
mappings (see Mappings class).

Functions to map (provide a path to the data given a dataset
identifier dictionary) and standardize (convert data into some standard
format or type) may be provided in the subclass as "map_{dataset type}"
and "std_{dataset type}", respectively.

If non-Exposure datasets cannot be retrieved using standard
daf_persistence methods alone, a "bypass_{dataset type}" function may be
provided in the subclass to return the dataset instead of using the
"datasets" subpolicy.

Implementations of map_camera and bypass_camera that should typically be
sufficient are provided in this base class.

@todo
* Handle defects the same was as all other calibration products, using the calibration registry
* Instead of auto-loading the camera at construction time, load it from the calibration registry
* Rewrite defects as AFW tables so we don't need pyfits to unpersist them; then remove all mention
  of pyfits from this package.

Definition at line 40 of file cameraMapper.py.

Constructor & Destructor Documentation

def lsst.daf.butlerUtils.cameraMapper.CameraMapper.__init__ (   self,
  policy,
  repositoryDir,
  root = None,
  registry = None,
  calibRoot = None,
  calibRegistry = None,
  provided = None,
  outputRoot = None 
)
Initialize the CameraMapper.
@param policy        (pexPolicy.Policy) Policy with per-camera defaults
             already merged
@param repositoryDir (string) Policy repository for the subclassing
             module (obtained with getRepositoryPath() on the
             per-camera default dictionary)
@param root          (string) Root directory for data
@param registry      (string) Path to registry with data's metadata
@param calibRoot     (string) Root directory for calibrations
@param calibRegistry (string) Path to registry with calibrations'
             metadata
@param provided      (list of strings) Keys provided by the mapper
@param outputRoot    (string) Root directory for output data

Definition at line 133 of file cameraMapper.py.

134  provided=None, outputRoot=None):
135  """Initialize the CameraMapper.
136  @param policy (pexPolicy.Policy) Policy with per-camera defaults
137  already merged
138  @param repositoryDir (string) Policy repository for the subclassing
139  module (obtained with getRepositoryPath() on the
140  per-camera default dictionary)
141  @param root (string) Root directory for data
142  @param registry (string) Path to registry with data's metadata
143  @param calibRoot (string) Root directory for calibrations
144  @param calibRegistry (string) Path to registry with calibrations'
145  metadata
146  @param provided (list of strings) Keys provided by the mapper
147  @param outputRoot (string) Root directory for output data
148  """
149 
150  dafPersist.Mapper.__init__(self)
152  self.log = pexLog.Log(pexLog.getDefaultLog(), "CameraMapper")
153 
154  # Dictionary
155  dictFile = pexPolicy.DefaultPolicyFile("daf_butlerUtils",
156  "MapperDictionary.paf", "policy")
157  dictPolicy = pexPolicy.Policy.createPolicy(dictFile,
158  dictFile.getRepositoryPath())
159  policy.mergeDefaults(dictPolicy)
160 
161  # Levels
162  self.levels = dict()
163  if policy.exists("levels"):
164  levelsPolicy = policy.getPolicy("levels")
165  for key in levelsPolicy.names(True):
166  self.levels[key] = set(levelsPolicy.getStringArray(key))
167  self.defaultLevel = policy.getString("defaultLevel")
168  self.defaultSubLevels = dict()
169  if policy.exists("defaultSubLevels"):
170  defaultSubLevelsPolicy = policy.getPolicy("defaultSubLevels")
171  for key in defaultSubLevelsPolicy.names(True):
172  self.defaultSubLevels[key] = defaultSubLevelsPolicy.getString(key)
173 
174  # Root directories
175  if root is None:
176  root = "."
177  root = dafPersist.LogicalLocation(root).locString()
178 
179  if outputRoot is not None and os.path.abspath(outputRoot) != os.path.abspath(root):
180  # Path manipulations are subject to race condition
181  if not os.path.exists(outputRoot):
182  try:
183  os.makedirs(outputRoot)
184  except OSError, e:
185  if not e.errno == errno.EEXIST:
186  raise
187  if not os.path.exists(outputRoot):
188  raise RuntimeError, "Unable to create output " \
189  "repository '%s'" % (outputRoot,)
190  if os.path.exists(root):
191  # Symlink existing input root to "_parent" in outputRoot.
192  src = os.path.abspath(root)
193  dst = os.path.join(outputRoot, "_parent")
194  if not os.path.exists(dst):
195  try:
196  os.symlink(src, dst)
197  except OSError:
198  pass
199  if os.path.exists(dst):
200  if os.path.realpath(dst) != os.path.realpath(src):
201  raise RuntimeError, "Output repository path " \
202  "'%s' already exists and differs from " \
203  "input repository path '%s'" % (dst, src)
204  else:
205  raise RuntimeError, "Unable to symlink from input " \
206  "repository path '%s' to output repository " \
207  "path '%s'" % (src, dst)
208  # We now use the outputRoot as the main root with access to the
209  # input via "_parent".
210  root = outputRoot
211 
212  if calibRoot is None:
213  if policy.exists('calibRoot'):
214  calibRoot = policy.getString('calibRoot')
215  calibRoot = dafPersist.LogicalLocation(calibRoot).locString()
216  else:
217  calibRoot = root
218 
219  if not os.path.exists(root):
220  self.log.log(pexLog.Log.WARN,
221  "Root directory not found: %s" % (root,))
222  if not os.path.exists(calibRoot):
223  self.log.log(pexLog.Log.WARN,
224  "Calibration root directory not found: %s" % (calibRoot,))
225  self.root = root
226 
227  # Registries
228  self.registry = self._setupRegistry(
229  "registry", registry, policy, "registryPath", root)
230  if policy.exists('needCalibRegistry') and \
231  policy.getBool('needCalibRegistry'):
232  calibRegistry = self._setupRegistry(
233  "calibRegistry", calibRegistry,
234  policy, "calibRegistryPath", calibRoot)
235  else:
236  calibRegistry = None
237 
238  # Sub-dictionaries (for exposure/calibration/dataset types)
239  imgMappingFile = pexPolicy.DefaultPolicyFile("daf_butlerUtils",
240  "ImageMappingDictionary.paf", "policy")
241  imgMappingPolicy = pexPolicy.Policy.createPolicy(imgMappingFile,
242  imgMappingFile.getRepositoryPath())
243  expMappingFile = pexPolicy.DefaultPolicyFile("daf_butlerUtils",
244  "ExposureMappingDictionary.paf", "policy")
245  expMappingPolicy = pexPolicy.Policy.createPolicy(expMappingFile,
246  expMappingFile.getRepositoryPath())
247  calMappingFile = pexPolicy.DefaultPolicyFile("daf_butlerUtils",
248  "CalibrationMappingDictionary.paf", "policy")
249  calMappingPolicy = pexPolicy.Policy.createPolicy(calMappingFile,
250  calMappingFile.getRepositoryPath())
251  dsMappingFile = pexPolicy.DefaultPolicyFile("daf_butlerUtils",
252  "DatasetMappingDictionary.paf", "policy")
253  dsMappingPolicy = pexPolicy.Policy.createPolicy(dsMappingFile,
254  dsMappingFile.getRepositoryPath())
255 
256  # Dict of valid keys and their value types
257  self.keyDict = dict()
258 
259  # Mappings
260  mappingList = (
261  ("images", imgMappingPolicy, ImageMapping),
262  ("exposures", expMappingPolicy, ExposureMapping),
263  ("calibrations", calMappingPolicy, CalibrationMapping),
264  ("datasets", dsMappingPolicy, DatasetMapping)
265  )
266  self.mappings = dict()
267  for name, defPolicy, cls in mappingList:
268  if policy.exists(name):
269  datasets = policy.getPolicy(name)
270  mappings = dict()
271  setattr(self, name, mappings)
272  for datasetType in datasets.names(True):
273  subPolicy = datasets.getPolicy(datasetType)
274  subPolicy.mergeDefaults(defPolicy)
275  if name == "calibrations":
276  mapping = cls(datasetType, subPolicy,
277  self.registry, calibRegistry, calibRoot, provided=provided)
278  else:
279  mapping = cls(datasetType, subPolicy,
280  self.registry, root, provided=provided)
281  self.keyDict.update(mapping.keys())
282  mappings[datasetType] = mapping
283  self.mappings[datasetType] = mapping
284  if not hasattr(self, "map_" + datasetType):
285  def mapClosure(dataId, write=False,
286  mapper=self, mapping=mapping):
287  return mapping.map(mapper, dataId, write)
288  setattr(self, "map_" + datasetType, mapClosure)
289  if not hasattr(self, "query_" + datasetType):
290  def queryClosure(key, format, dataId, mapping=mapping):
291  return mapping.lookup(format, dataId)
292  setattr(self, "query_" + datasetType, queryClosure)
293  if hasattr(mapping, "standardize") and \
294  not hasattr(self, "std_" + datasetType):
295  def stdClosure(item, dataId,
296  mapper=self, mapping=mapping):
297  return mapping.standardize(mapper, item, dataId)
298  setattr(self, "std_" + datasetType, stdClosure)
299 
300  mapFunc = "map_" + datasetType + "_filename"
301  bypassFunc = "bypass_" + datasetType + "_filename"
302  if not hasattr(self, mapFunc):
303  setattr(self, mapFunc, getattr(self, "map_" + datasetType))
304  if not hasattr(self, bypassFunc):
305  setattr(self, bypassFunc,
306  lambda datasetType, pythonType, location, dataId: location.getLocations())
307 
308  # Set up metadata versions
309  if name == "exposures" or name == "images":
310  expFunc = "map_" + datasetType # Function name to map exposure
311  mdFunc = expFunc + "_md" # Function name to map metadata
312  bypassFunc = "bypass_" + datasetType + "_md" # Function name to bypass daf_persistence
313  if not hasattr(self, mdFunc):
314  setattr(self, mdFunc, getattr(self, expFunc))
315  if not hasattr(self, bypassFunc):
316  setattr(self, bypassFunc,
317  lambda datasetType, pythonType, location, dataId:
318  afwImage.readMetadata(location.getLocations()[0]))
319  if not hasattr(self, "query_" + datasetType + "_md"):
320  setattr(self, "query_" + datasetType + "_md",
321  getattr(self, "query_" + datasetType))
322 
323  subFunc = expFunc + "_sub" # Function name to map subimage
324  if not hasattr(self, subFunc):
325  def mapSubClosure(dataId, write=False, mapper=self, mapping=mapping):
326  subId = dataId.copy()
327  del subId['bbox']
328  loc = mapping.map(mapper, subId, write)
329  bbox = dataId['bbox']
330  llcX = bbox.getMinX()
331  llcY = bbox.getMinY()
332  width = bbox.getWidth()
333  height = bbox.getHeight()
334  loc.additionalData.set('llcX', llcX)
335  loc.additionalData.set('llcY', llcY)
336  loc.additionalData.set('width', width)
337  loc.additionalData.set('height', height)
338  if 'imageOrigin' in dataId:
339  loc.additionalData.set('imageOrigin',
340  dataId['imageOrigin'])
341  return loc
342  setattr(self, subFunc, mapSubClosure)
343  if not hasattr(self, "query_" + datasetType + "_sub"):
344  def querySubClosure(key, format, dataId, mapping=mapping):
345  subId = dataId.copy()
346  del subId['bbox']
347  return mapping.lookup(format, subId)
348  setattr(self, "query_" + datasetType + "_sub", querySubClosure)
349 
350  # Camera geometry
351  self.cameraDataLocation = None # path to camera geometry config file
352  self.camera = self._makeCamera(policy=policy, repositoryDir=repositoryDir)
353 
354  # Defect registry and root
355  self.defectRegistry = None
356  if policy.exists('defects'):
357  self.defectPath = os.path.join(
358  repositoryDir, policy.getString('defects'))
359  defectRegistryLocation = os.path.join(
360  self.defectPath, "defectRegistry.sqlite3")
361  self.defectRegistry = \
362  Registry.create(defectRegistryLocation)
363 
364  # Filter translation table
365  self.filters = None
366 
367  # Skytile policy
368  self.skypolicy = policy.getPolicy("skytiles")
369 
370  # verify that the class variable packageName is set before attempting
371  # to instantiate an instance
372  if self.packageName is None:
373  raise ValueError('class variable packageName must not be None')
Class for logical location of a persisted Persistable instance.
a representation of a default Policy file that is stored as a file in the installation directory of a...
a place to record messages and descriptions of the state of processing.
Definition: Log.h:154
boost::shared_ptr< daf::base::PropertySet > readMetadata(std::string const &fileName, int hdu=0, bool strip=false)
Return the metadata (header entries) from a FITS file.

Member Function Documentation

def lsst.daf.butlerUtils.cameraMapper.CameraMapper._defectLookup (   self,
  dataId 
)
private
Find the defects for a given CCD.
@param dataId (dict) Dataset identifier
@return (string) path to the defects file or None if not available

Definition at line 784 of file cameraMapper.py.

785  def _defectLookup(self, dataId):
786  """Find the defects for a given CCD.
787  @param dataId (dict) Dataset identifier
788  @return (string) path to the defects file or None if not available"""
789  if self.defectRegistry is None:
790  return None
791  if self.registry is None:
792  raise RuntimeError, "No registry for defect lookup"
793 
794  ccdKey, ccdVal = self._getCcdKeyVal(dataId)
795 
796  rows = self.registry.executeQuery(("taiObs",), ("raw_visit",),
797  [("visit", "?")], None, (dataId['visit'],))
798  if len(rows) == 0:
799  return None
800  assert len(rows) == 1
801  taiObs = rows[0][0]
802 
803  # Lookup the defects for this CCD serial number that are valid at the
804  # exposure midpoint.
805  rows = self.defectRegistry.executeQuery(("path",), ("defect",),
806  [(ccdKey, "?")],
807  ("DATETIME(?)", "DATETIME(validStart)", "DATETIME(validEnd)"),
808  (ccdVal, taiObs))
809  if not rows or len(rows) == 0:
810  return None
811  if len(rows) == 1:
812  return os.path.join(self.defectPath, rows[0][0])
813  else:
814  raise RuntimeError("Querying for defects (%s, %s) returns %d files: %s" %
815  (ccdVal, taiObs, len(rows), ", ".join([_[0] for _ in rows])))
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._extractAmpId (   self,
  dataId 
)
private
Extract the amplifier identifer from a dataset identifier.

@warning this is deprecated; DO NOT USE IT

amplifier identifier has two parts: the detector name for the CCD
containing the amplifier and index of the amplifier in the detector.
@param dataId (dict) Dataset identifer
@return (tuple) Amplifier identifier

Definition at line 685 of file cameraMapper.py.

686  def _extractAmpId(self, dataId):
687  """Extract the amplifier identifer from a dataset identifier.
688 
689  @warning this is deprecated; DO NOT USE IT
690 
691  amplifier identifier has two parts: the detector name for the CCD
692  containing the amplifier and index of the amplifier in the detector.
693  @param dataId (dict) Dataset identifer
694  @return (tuple) Amplifier identifier"""
695 
696  trDataId = self._transformId(dataId)
697  return (trDataId["ccd"], int(trDataId['amp']))
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._extractDetectorName (   self,
  dataId 
)
private
Extract the detector (CCD) name from the dataset identifier.

The name in question is the detector name used by lsst.afw.cameraGeom.

@param dataId (dict) Dataset identifier
@return (string) Detector name

Definition at line 675 of file cameraMapper.py.

676  def _extractDetectorName(self, dataId):
677  """Extract the detector (CCD) name from the dataset identifier.
678 
679  The name in question is the detector name used by lsst.afw.cameraGeom.
680 
681  @param dataId (dict) Dataset identifier
682  @return (string) Detector name
683  """
684  raise NotImplementedError("No _extractDetectorName() function specified")
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._getCcdKeyVal (   self,
  dataId 
)
private

Utility functions.

Return CCD key and value used to look a defect in the defect registry

The default implementation simply returns ("ccd", full detector name)

Definition at line 583 of file cameraMapper.py.

584  def _getCcdKeyVal(self, dataId):
585  """Return CCD key and value used to look a defect in the defect registry
586 
587  The default implementation simply returns ("ccd", full detector name)
588  """
589  return ("ccd", self._extractDetectorName(dataId))
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._makeCamera (   self,
  policy,
  repositoryDir 
)
private
Make a camera (instance of lsst.afw.cameraGeom.Camera) describing the camera geometry

Also set self.cameraDataLocation, if relevant (else it can be left None).

This implementation assumes that policy contains an entry "camera" that points to the
subdirectory in this package of camera data; specifically, that subdirectory must contain:
- a file named `camera.py` that contains persisted camera config
- ampInfo table FITS files, as required by lsst.afw.cameraGeom.makeCameraFromPath

@param policy        (pexPolicy.Policy) Policy with per-camera defaults
             already merged
@param repositoryDir (string) Policy repository for the subclassing
             module (obtained with getRepositoryPath() on the
             per-camera default dictionary)

Definition at line 816 of file cameraMapper.py.

817  def _makeCamera(self, policy, repositoryDir):
818  """Make a camera (instance of lsst.afw.cameraGeom.Camera) describing the camera geometry
819 
820  Also set self.cameraDataLocation, if relevant (else it can be left None).
821 
822  This implementation assumes that policy contains an entry "camera" that points to the
823  subdirectory in this package of camera data; specifically, that subdirectory must contain:
824  - a file named `camera.py` that contains persisted camera config
825  - ampInfo table FITS files, as required by lsst.afw.cameraGeom.makeCameraFromPath
826 
827  @param policy (pexPolicy.Policy) Policy with per-camera defaults
828  already merged
829  @param repositoryDir (string) Policy repository for the subclassing
830  module (obtained with getRepositoryPath() on the
831  per-camera default dictionary)
832  """
833  if not policy.exists('camera'):
834  raise RuntimeError("Cannot find 'camera' in policy; cannot construct a camera")
835 
836  cameraDataSubdir = policy.getString('camera')
837  self.cameraDataLocation = os.path.normpath(
838  os.path.join(repositoryDir, cameraDataSubdir, "camera.py"))
839  cameraConfig = afwCameraGeom.CameraConfig()
840  cameraConfig.load(self.cameraDataLocation)
841  ampInfoPath = os.path.dirname(self.cameraDataLocation)
842  return afwCameraGeom.makeCameraFromPath(
843  cameraConfig = cameraConfig,
844  ampInfoPath = ampInfoPath,
845  shortNameFunc = self.getShortCcdName
846  )
847 
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._mapActualToPath (   self,
  template,
  actualId 
)
private
Convert a template path to an actual path, using the actual data
identifier.  This implementation is usually sufficient but can be
overridden by the subclass.
@param template (string) Template path
@param actualId (dict) Dataset identifier
@return (string) Pathname

Definition at line 657 of file cameraMapper.py.

658  def _mapActualToPath(self, template, actualId):
659  """Convert a template path to an actual path, using the actual data
660  identifier. This implementation is usually sufficient but can be
661  overridden by the subclass.
662  @param template (string) Template path
663  @param actualId (dict) Dataset identifier
664  @return (string) Pathname"""
665 
666  return template % self._transformId(actualId)
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._parentSearch (   self,
  path 
)
private
Look for the given path in the current root or any of its parents
by following "_parent" symlinks; return None if it can't be found.  A
little tricky because the path may be in an alias of the root (e.g.
".") and because the "_parent" links go between the root and the rest
of the path.

Definition at line 374 of file cameraMapper.py.

375  def _parentSearch(self, path):
376  """Look for the given path in the current root or any of its parents
377  by following "_parent" symlinks; return None if it can't be found. A
378  little tricky because the path may be in an alias of the root (e.g.
379  ".") and because the "_parent" links go between the root and the rest
380  of the path.
381  """
382 
383  # Separate path into a root-equivalent prefix (in dir) and the rest
384  # (left in path)
385  rootDir = self.root
386 
387  # First remove trailing slashes (#2527)
388  while len(rootDir) > 1 and rootDir[-1] == '/':
389  rootDir = rootDir[:-1]
390 
391  if path.startswith(rootDir + "/"):
392  # Common case; we have the same root prefix string
393  path = path[len(rootDir)+1:]
394  dir = rootDir
395  elif rootDir == "/" and path.startswith("/"):
396  path = path[1:]
397  dir = rootDir
398  else:
399  # Search for prefix that is the same as root
400  pathPrefix = os.path.dirname(path)
401  while pathPrefix != "" and pathPrefix != "/":
402  if os.path.realpath(pathPrefix) == os.path.realpath(self.root):
403  break
404  pathPrefix = os.path.dirname(pathPrefix)
405  if os.path.realpath(pathPrefix) != os.path.realpath(self.root):
406  # No prefix matching root, don't search for parents
407  if os.path.exists(path):
408  return path
409  return None
410  if pathPrefix == "/":
411  path = path[1:]
412  elif pathPrefix != "":
413  path = path[len(pathPrefix)+1:]
414  # If pathPrefix == "", then the current directory is the root
415  dir = pathPrefix
416 
417  # Now search for the path in the root or its parents
418  # Strip off any cfitsio bracketed extension if present
419  strippedPath = path
420  firstBracket = path.find("[")
421  if firstBracket != -1:
422  strippedPath = path[:firstBracket]
423  while not os.path.exists(os.path.join(dir, strippedPath)):
424  dir = os.path.join(dir, "_parent")
425  if not os.path.exists(dir):
426  return None
427  return os.path.join(dir, path)
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._setAmpDetector (   self,
  item,
  dataId,
  trimmed = True 
)
private
Set the detector object in an Exposure for an amplifier.
Defects are also added to the Exposure based on the detector object.
@param[in,out] item (lsst.afw.image.Exposure)
@param dataId (dict) Dataset identifier
@param trimmed (bool) Should detector be marked as trimmed? (ignored)

Definition at line 698 of file cameraMapper.py.

699  def _setAmpDetector(self, item, dataId, trimmed=True):
700  """Set the detector object in an Exposure for an amplifier.
701  Defects are also added to the Exposure based on the detector object.
702  @param[in,out] item (lsst.afw.image.Exposure)
703  @param dataId (dict) Dataset identifier
704  @param trimmed (bool) Should detector be marked as trimmed? (ignored)"""
705 
706  return self._setCcdDetector(item=item, dataId=dataId, trimmed=trimmed)
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._setCcdDetector (   self,
  item,
  dataId,
  trimmed = True 
)
private
Set the detector object in an Exposure for a CCD.
@param[in,out] item (lsst.afw.image.Exposure)
@param dataId (dict) Dataset identifier
@param trimmed (bool) Should detector be marked as trimmed? (ignored)

Definition at line 707 of file cameraMapper.py.

708  def _setCcdDetector(self, item, dataId, trimmed=True):
709  """Set the detector object in an Exposure for a CCD.
710  @param[in,out] item (lsst.afw.image.Exposure)
711  @param dataId (dict) Dataset identifier
712  @param trimmed (bool) Should detector be marked as trimmed? (ignored)"""
713 
714  detectorName = self._extractDetectorName(dataId)
715  detector = self.camera[detectorName]
716  item.setDetector(detector)
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._setFilter (   self,
  mapping,
  item,
  dataId 
)
private
Set the filter object in an Exposure.  If the Exposure had a FILTER
keyword, this was already processed during load.  But if it didn't,
use the filter from the registry.
@param mapping (lsst.daf.butlerUtils.Mapping)
@param[in,out] item (lsst.afw.image.Exposure)
@param dataId (dict) Dataset identifier

Definition at line 717 of file cameraMapper.py.

718  def _setFilter(self, mapping, item, dataId):
719  """Set the filter object in an Exposure. If the Exposure had a FILTER
720  keyword, this was already processed during load. But if it didn't,
721  use the filter from the registry.
722  @param mapping (lsst.daf.butlerUtils.Mapping)
723  @param[in,out] item (lsst.afw.image.Exposure)
724  @param dataId (dict) Dataset identifier"""
725 
726  if not (isinstance(item, afwImage.ExposureU) or isinstance(item, afwImage.ExposureI) or
727  isinstance(item, afwImage.ExposureF) or isinstance(item, afwImage.ExposureD)):
728  return
729 
730  actualId = mapping.need(['filter'], dataId)
731  filterName = actualId['filter']
732  if self.filters is not None and self.filters.has_key(filterName):
733  filterName = self.filters[filterName]
734  item.setFilter(afwImage.Filter(filterName))
Holds an integer identifier for an LSST filter.
Definition: Filter.h:107
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._setTimes (   self,
  mapping,
  item,
  dataId 
)
private
Set the exposure time and exposure midpoint in the calib object in
an Exposure.  Use the EXPTIME and MJD-OBS keywords (and strip out
EXPTIME).
@param mapping (lsst.daf.butlerUtils.Mapping)
@param[in,out] item (lsst.afw.image.Exposure)
@param dataId (dict) Dataset identifier

Definition at line 735 of file cameraMapper.py.

736  def _setTimes(self, mapping, item, dataId):
737  """Set the exposure time and exposure midpoint in the calib object in
738  an Exposure. Use the EXPTIME and MJD-OBS keywords (and strip out
739  EXPTIME).
740  @param mapping (lsst.daf.butlerUtils.Mapping)
741  @param[in,out] item (lsst.afw.image.Exposure)
742  @param dataId (dict) Dataset identifier"""
743 
744  md = item.getMetadata()
745  calib = item.getCalib()
746  if md.exists("EXPTIME"):
747  expTime = md.get("EXPTIME")
748  calib.setExptime(expTime)
749  md.remove("EXPTIME")
750  else:
751  expTime = calib.getExptime()
752  if md.exists("MJD-OBS"):
753  obsStart = dafBase.DateTime(md.get("MJD-OBS"),
754  dafBase.DateTime.MJD, dafBase.DateTime.UTC)
755  obsMidpoint = obsStart.nsecs() + long(expTime * 1000000000L / 2)
756  calib.setMidTime(dafBase.DateTime(obsMidpoint))
757 
Class for handling dates/times, including MJD, UTC, and TAI.
Definition: DateTime.h:58
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._setupRegistry (   self,
  name,
  path,
  policy,
  policyKey,
  root 
)
private
Set up a registry (usually SQLite3), trying a number of possible
paths.
@param name       (string) Name of registry
@param path       (string) Path for registry
@param policyKey  (string) Key in policy for registry path
@param root       (string) Root directory to look in
@return (lsst.daf.butlerUtils.Registry) Registry object

Definition at line 590 of file cameraMapper.py.

591  def _setupRegistry(self, name, path, policy, policyKey, root):
592  """Set up a registry (usually SQLite3), trying a number of possible
593  paths.
594  @param name (string) Name of registry
595  @param path (string) Path for registry
596  @param policyKey (string) Key in policy for registry path
597  @param root (string) Root directory to look in
598  @return (lsst.daf.butlerUtils.Registry) Registry object"""
599 
600  if path is None and policy.exists(policyKey):
602  policy.getString(policyKey)).locString()
603  if not os.path.exists(path):
604  if not os.path.isabs(path) and root is not None:
605  newPath = self._parentSearch(os.path.join(root, path))
606  if newPath is None:
607  self.log.log(pexLog.Log.WARN,
608  "Unable to locate registry at policy path (also looked in root): %s" % path)
609  path = newPath
610  else:
611  self.log.log(pexLog.Log.WARN,
612  "Unable to locate registry at policy path: %s" % path)
613  path = None
614  if path is None and root is not None:
615  path = os.path.join(root, "%s.sqlite3" % name)
616  newPath = self._parentSearch(path)
617  if newPath is None:
618  self.log.log(pexLog.Log.WARN,
619  "Unable to locate %s registry in root: %s" % (name, path))
620  path = newPath
621  if path is None:
622  path = os.path.join(".", "%s.sqlite3" % name)
623  newPath = self._parentSearch(path)
624  if newPath is None:
625  self.log.log(pexLog.Log.WARN,
626  "Unable to locate %s registry in current dir: %s" % (name, path))
627  path = newPath
628  if path is not None:
629  if not os.path.exists(path):
630  newPath = self._parentSearch(path)
631  if newPath is not None:
632  path = newPath
633  self.log.log(pexLog.Log.INFO,
634  "Loading %s registry from %s" % (name, path))
635  registry = Registry.create(path)
636  if registry is None:
637  raise RuntimeError, "Unable to load %s registry from %s" % (name, path)
638  return registry
639  else:
640  # TODO Try a FsRegistry(root)
641  self.log.log(pexLog.Log.WARN,
642  "No registry loaded; proceeding without one")
643  return None
Class for logical location of a persisted Persistable instance.
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._standardizeExposure (   self,
  mapping,
  item,
  dataId,
  filter = True,
  trimmed = True 
)
private
Default standardization function for images.
@param mapping (lsst.daf.butlerUtils.Mapping)
@param[in,out] item (lsst.afw.image.Exposure)
@param dataId (dict) Dataset identifier
@param filter (bool) Set filter?
@param trimmed (bool) Should detector be marked as trimmed?
@return (lsst.afw.image.Exposure) the standardized Exposure

Definition at line 760 of file cameraMapper.py.

761  trimmed=True):
762  """Default standardization function for images.
763  @param mapping (lsst.daf.butlerUtils.Mapping)
764  @param[in,out] item (lsst.afw.image.Exposure)
765  @param dataId (dict) Dataset identifier
766  @param filter (bool) Set filter?
767  @param trimmed (bool) Should detector be marked as trimmed?
768  @return (lsst.afw.image.Exposure) the standardized Exposure"""
769 
770  if (re.search(r'Exposure', mapping.python) and re.search(r'Image',mapping.persistable)):
771  item = exposureFromImage(item)
772 
773  if mapping.level.lower() == "amp":
774  self._setAmpDetector(item, dataId, trimmed)
775  elif mapping.level.lower() == "ccd":
776  self._setCcdDetector(item, dataId, trimmed)
777 
778  if filter:
779  self._setFilter(mapping, item, dataId)
780  if not isinstance(mapping, CalibrationMapping):
781  self._setTimes(mapping, item, dataId)
782 
783  return item
def lsst.daf.butlerUtils.cameraMapper.CameraMapper._transformId (   self,
  dataId 
)
private
Generate a standard ID dict from a camera-specific ID dict.

Canonical keys include:
- amp: amplifier name
- ccd: CCD name (in LSST this is a combination of raft and sensor)
The default implementation returns a copy of its input.

@param dataId[in] (dict) Dataset identifier; this must not be modified
@return (dict) Transformed dataset identifier

Definition at line 644 of file cameraMapper.py.

645  def _transformId(self, dataId):
646  """Generate a standard ID dict from a camera-specific ID dict.
647 
648  Canonical keys include:
649  - amp: amplifier name
650  - ccd: CCD name (in LSST this is a combination of raft and sensor)
651  The default implementation returns a copy of its input.
652 
653  @param dataId[in] (dict) Dataset identifier; this must not be modified
654  @return (dict) Transformed dataset identifier"""
655 
656  return dataId.copy()
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.backup (   self,
  datasetType,
  dataId 
)
Rename any existing object with the given type and dataId.

The CameraMapper implementation saves objects in a sequence of e.g.:
  foo.fits
  foo.fits~1
  foo.fits~2
All of the backups will be placed in the output repo, however, and will
not be removed if they are found elsewhere in the _parent chain.  This
means that the same file will be stored twice if the previous version was
found in an input repo.

Definition at line 428 of file cameraMapper.py.

429  def backup(self, datasetType, dataId):
430  """Rename any existing object with the given type and dataId.
431 
432  The CameraMapper implementation saves objects in a sequence of e.g.:
433  foo.fits
434  foo.fits~1
435  foo.fits~2
436  All of the backups will be placed in the output repo, however, and will
437  not be removed if they are found elsewhere in the _parent chain. This
438  means that the same file will be stored twice if the previous version was
439  found in an input repo.
440  """
441  n = 0
442  newLocation = self.map(datasetType, dataId, write=True)
443  newPath = newLocation.getLocations()[0]
444  path = self._parentSearch(newPath)
445  oldPaths = []
446  while path is not None:
447  n += 1
448  oldPaths.append((n, path))
449  path = self._parentSearch("%s~%d" % (newPath, n))
450  for n, oldPath in reversed(oldPaths):
451  newDir, newFile = os.path.split(newPath)
452  if not os.path.exists(newDir):
453  os.makedirs(newDir)
454  shutil.copy(oldPath, "%s~%d" % (newPath, n))
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.bypass_camera (   self,
  datasetType,
  pythonType,
  butlerLocation,
  dataId 
)
Return the (preloaded) camera object.

Definition at line 516 of file cameraMapper.py.

517  def bypass_camera(self, datasetType, pythonType, butlerLocation, dataId):
518  """Return the (preloaded) camera object.
519  """
520  if self.camera is None:
521  raise RuntimeError("No camera dataset available.")
522  return self.camera
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.bypass_defects (   self,
  datasetType,
  pythonType,
  butlerLocation,
  dataId 
)
Return a defect based on the butler location returned by map_defects

@param[in] butlerLocation: a ButlerLocation with locationList = path to defects FITS file
@param[in] dataId: the usual data ID; "ccd" must be set

Note: the name "bypass_XXX" means the butler makes no attempt to convert the ButlerLocation
into an object, which is what we want for now, since that conversion is a bit tricky.

Definition at line 535 of file cameraMapper.py.

536  def bypass_defects(self, datasetType, pythonType, butlerLocation, dataId):
537  """Return a defect based on the butler location returned by map_defects
538 
539  @param[in] butlerLocation: a ButlerLocation with locationList = path to defects FITS file
540  @param[in] dataId: the usual data ID; "ccd" must be set
541 
542  Note: the name "bypass_XXX" means the butler makes no attempt to convert the ButlerLocation
543  into an object, which is what we want for now, since that conversion is a bit tricky.
544  """
545  detectorName = self._extractDetectorName(dataId)
546  defectsFitsPath = butlerLocation.locationList[0]
547  with pyfits.open(defectsFitsPath) as hduList:
548  for hdu in hduList[1:]:
549  if hdu.header["name"] != detectorName:
550  continue
551 
552  defectList = []
553  for data in hdu.data:
554  bbox = afwGeom.Box2I(
555  afwGeom.Point2I(int(data['x0']), int(data['y0'])),
556  afwGeom.Extent2I(int(data['width']), int(data['height'])),
557  )
558  defectList.append(afwImage.DefectBase(bbox))
559  return defectList
560 
561  raise RuntimeError("No defects for ccd %s in %s" % (detectorName, defectsFitsPath))
Encapsulate information about a bad portion of a detector.
Definition: Defect.h:42
An integer coordinate rectangle.
Definition: Box.h:53
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.getCameraName (   cls)
Return the name of the camera that this CameraMapper is for.

Definition at line 487 of file cameraMapper.py.

488  def getCameraName(cls):
489  """Return the name of the camera that this CameraMapper is for."""
490  className = str(cls)
491  m = re.search(r'(\w+)Mapper', className)
492  if m is None:
493  m = re.search(r"class '[\w.]*?(\w+)'", className)
494  name = m.group(1)
495  return name[:1].lower() + name[1:] if name else ''
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.getDefaultLevel (   self)

Definition at line 478 of file cameraMapper.py.

479  def getDefaultLevel(self):
480  return self.defaultLevel
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.getDefaultSubLevel (   self,
  level 
)

Definition at line 481 of file cameraMapper.py.

482  def getDefaultSubLevel(self, level):
483  if self.defaultSubLevels.has_key(level):
484  return self.defaultSubLevels[level]
485  return None
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.getKeys (   self,
  datasetType,
  level 
)
Return supported keys and their value types for a given dataset
type at a given level of the key hierarchy.

@param datasetType (str) dataset type or None for all keys
@param level (str) level or None for all levels
@return (iterable) Set of keys usable in a dataset identifier

Definition at line 460 of file cameraMapper.py.

461  def getKeys(self, datasetType, level):
462  """Return supported keys and their value types for a given dataset
463  type at a given level of the key hierarchy.
464 
465  @param datasetType (str) dataset type or None for all keys
466  @param level (str) level or None for all levels
467  @return (iterable) Set of keys usable in a dataset identifier"""
468  if datasetType is None:
469  keyDict = self.keyDict
470  else:
471  keyDict = self.mappings[datasetType].keys()
472  if level is not None and level in self.levels:
473  keyDict = dict(keyDict)
474  for l in self.levels[level]:
475  if l in keyDict:
476  del keyDict[l]
477  return keyDict
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.getPackageName (   cls)
Return the name of the package containing this CameraMapper.

Definition at line 497 of file cameraMapper.py.

498  def getPackageName(cls):
499  """Return the name of the package containing this CameraMapper."""
500  if cls.packageName is None:
501  raise ValueError('class variable packageName must not be None')
502  return cls.packageName
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.getShortCcdName (   ccdName)
static
Convert a CCD name to a form useful as a filename

The default implementation converts spaces to underscores.

Definition at line 668 of file cameraMapper.py.

669  def getShortCcdName(ccdName):
670  """Convert a CCD name to a form useful as a filename
671 
672  The default implementation converts spaces to underscores.
673  """
674  return ccdName.replace(" ", "_")
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.keys (   self)
Return supported keys.
@return (iterable) List of keys usable in a dataset identifier

Definition at line 455 of file cameraMapper.py.

456  def keys(self):
457  """Return supported keys.
458  @return (iterable) List of keys usable in a dataset identifier"""
459  return self.keyDict.iterkeys()
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.map_camera (   self,
  dataId,
  write = False 
)
Map a camera dataset.

Definition at line 503 of file cameraMapper.py.

504  def map_camera(self, dataId, write=False):
505  """Map a camera dataset."""
506  if self.camera is None:
507  raise RuntimeError("No camera dataset available.")
508  actualId = self._transformId(dataId)
510  pythonType = "lsst.afw.cameraGeom.CameraConfig",
511  cppType = "Config",
512  storageName = "ConfigStorage",
513  locationList = self.cameraDataLocation or "ignored",
514  dataId = actualId,
515  )
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.map_defects (   self,
  dataId,
  write = False 
)
Map defects dataset.

@return a very minimal ButlerLocation containing just the locationList field
    (just enough information that bypass_defects can use it).

Definition at line 523 of file cameraMapper.py.

524  def map_defects(self, dataId, write=False):
525  """Map defects dataset.
526 
527  @return a very minimal ButlerLocation containing just the locationList field
528  (just enough information that bypass_defects can use it).
529  """
530  defectFitsPath = self._defectLookup(dataId=dataId)
531  if defectFitsPath is None:
532  raise RuntimeError("No defects available for dataId=%s" % (dataId,))
533 
534  return dafPersist.ButlerLocation(None, None, None, defectFitsPath, dataId)
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.map_skypolicy (   self,
  dataId 
)
Map a sky policy.

Definition at line 568 of file cameraMapper.py.

569  def map_skypolicy(self, dataId):
570  """Map a sky policy."""
571  return dafPersist.ButlerLocation("lsst.pex.policy.Policy", "Policy",
572  "Internal", None, None)
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.std_raw (   self,
  item,
  dataId 
)
Standardize a raw dataset by converting it to an Exposure instead of an Image

Definition at line 562 of file cameraMapper.py.

563  def std_raw(self, item, dataId):
564  """Standardize a raw dataset by converting it to an Exposure instead of an Image"""
565  item = exposureFromImage(item)
566  return self._standardizeExposure(self.exposures['raw'], item, dataId,
567  trimmed=False)
def lsst.daf.butlerUtils.cameraMapper.CameraMapper.std_skypolicy (   self,
  item,
  dataId 
)
Standardize a sky policy by returning the one we use.

Definition at line 573 of file cameraMapper.py.

574  def std_skypolicy(self, item, dataId):
575  """Standardize a sky policy by returning the one we use."""
576  return self.skypolicy

Member Data Documentation

lsst.daf.butlerUtils.cameraMapper.CameraMapper.camera

Definition at line 351 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.cameraDataLocation

Definition at line 350 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.defaultLevel

Definition at line 166 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.defaultSubLevels

Definition at line 167 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.defectPath

Definition at line 356 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.defectRegistry

Definition at line 354 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.filters

Definition at line 364 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.keyDict

Definition at line 256 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.levels

Definition at line 161 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.log

Definition at line 151 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.mappings

Definition at line 265 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.packageName = None
static

Definition at line 129 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.registry

Definition at line 227 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.root

Definition at line 224 of file cameraMapper.py.

lsst.daf.butlerUtils.cameraMapper.CameraMapper.skypolicy

Definition at line 367 of file cameraMapper.py.


The documentation for this class was generated from the following file: