32 from lsst.daf.butlerUtils import ImageMapping, ExposureMapping, CalibrationMapping, DatasetMapping, Registry
40 """This module defines the CameraMapper base class."""
44 """CameraMapper is a base class for mappers that handle images from a
45 camera and products derived from them. This provides an abstraction layer
46 between the data on disk and the code.
48 Public methods: keys, queryMetadata, getDatasetTypes, map,
49 canStandardize, standardize
51 Mappers for specific data sources (e.g., CFHT Megacam, LSST
52 simulations, etc.) should inherit this class.
54 The CameraMapper manages datasets within a "root" directory. It can also
55 be given an "outputRoot". If so, the input root is linked into the
56 outputRoot directory using a symlink named "_parent"; writes go into the
57 outputRoot while reads can come from either the root or outputRoot. As
58 outputRoots are used as inputs for further processing, the chain of
59 _parent links allows any dataset to be retrieved. Note that writing to a
60 dataset present in the input root will hide the existing dataset but not
61 overwrite it. See #2160 for design discussion.
63 A camera is assumed to consist of one or more rafts, each composed of
64 multiple CCDs. Each CCD is in turn composed of one or more amplifiers
65 (amps). A camera is also assumed to have a camera geometry description
66 (CameraGeom object) as a policy file, a filter description (Filter class
67 static configuration) as another policy file, and an optional defects
68 description directory.
70 Information from the camera geometry and defects are inserted into all
71 Exposure objects returned.
73 The mapper uses one or two registries to retrieve metadata about the
74 images. The first is a registry of all raw exposures. This must contain
75 the time of the observation. One or more tables (or the equivalent)
76 within the registry are used to look up data identifier components that
77 are not specified by the user (e.g. filter) and to return results for
78 metadata queries. The second is an optional registry of all calibration
79 data. This should contain validity start and end entries for each
80 calibration dataset in the same timescale as the observation time.
82 The following method must be provided by the subclass:
84 _extractDetectorName(self, dataId): returns the detector name for a CCD
85 (e.g., "CFHT 21", "R:1,2 S:3,4") as used in the AFW CameraGeom class given
86 a dataset identifier referring to that CCD or a subcomponent of it.
88 Other methods that the subclass may wish to override include:
90 _transformId(self, dataId): transformation of a data identifier
91 from colloquial usage (e.g., "ccdname") to proper/actual usage (e.g., "ccd"),
92 including making suitable for path expansion (e.g. removing commas).
93 The default implementation does nothing. Note that this
94 method should not modify its input parameter.
96 getShortCcdName(self, ccdName): a static method that returns a shortened name
97 suitable for use as a filename. The default version converts spaces to underscores.
99 _getCcdKeyVal(self, dataId): return a CCD key and value
100 by which to look up defects in the defects registry.
101 The default value returns ("ccd", detector name)
103 _mapActualToPath(self, template, actualId): convert a template path to an
104 actual path, using the actual dataset identifier.
106 The mapper's behaviors are largely specified by the policy file.
107 See the MapperDictionary.paf for descriptions of the available items.
109 The 'exposures', 'calibrations', and 'datasets' subpolicies configure
110 mappings (see Mappings class).
112 Functions to map (provide a path to the data given a dataset
113 identifier dictionary) and standardize (convert data into some standard
114 format or type) may be provided in the subclass as "map_{dataset type}"
115 and "std_{dataset type}", respectively.
117 If non-Exposure datasets cannot be retrieved using standard
118 daf_persistence methods alone, a "bypass_{dataset type}" function may be
119 provided in the subclass to return the dataset instead of using the
120 "datasets" subpolicy.
122 Implementations of map_camera and std_camera that should typically be
123 sufficient are provided in this base class.
126 * Handle defects the same was as all other calibration products, using the calibration registry
127 * Instead of auto-loading the camera at construction time, load it from the calibration registry
128 * Rewrite defects as AFW tables so we don't need pyfits to unpersist them; then remove all mention
129 of pyfits from this package.
132 def __init__(self, policy, repositoryDir,
133 root=
None, registry=
None, calibRoot=
None, calibRegistry=
None,
134 provided=
None, outputRoot=
None):
135 """Initialize the CameraMapper.
136 @param policy (pexPolicy.Policy) Policy with per-camera defaults
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'
146 @param provided (list of strings) Keys provided by the mapper
147 @param outputRoot (string) Root directory for output data
150 dafPersist.Mapper.__init__(self)
156 "MapperDictionary.paf",
"policy")
157 dictPolicy = pexPolicy.Policy.createPolicy(dictFile,
158 dictFile.getRepositoryPath())
159 policy.mergeDefaults(dictPolicy)
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))
169 if policy.exists(
"defaultSubLevels"):
170 defaultSubLevelsPolicy = policy.getPolicy(
"defaultSubLevels")
171 for key
in defaultSubLevelsPolicy.names(
True):
179 if outputRoot
is not None and os.path.abspath(outputRoot) != os.path.abspath(root):
181 if not os.path.exists(outputRoot):
183 os.makedirs(outputRoot)
185 if not e.errno == errno.EEXIST:
187 if not os.path.exists(outputRoot):
188 raise RuntimeError,
"Unable to create output " \
189 "repository '%s'" % (outputRoot,)
190 if os.path.exists(root):
192 src = os.path.abspath(root)
193 dst = os.path.join(outputRoot,
"_parent")
194 if not os.path.exists(dst):
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)
205 raise RuntimeError,
"Unable to symlink from input " \
206 "repository path '%s' to output repository " \
207 "path '%s'" % (src, dst)
212 if calibRoot
is None:
213 if policy.exists(
'calibRoot'):
214 calibRoot = policy.getString(
'calibRoot')
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,))
229 "registry", registry, policy,
"registryPath", root)
230 if policy.exists(
'needCalibRegistry')
and \
231 policy.getBool(
'needCalibRegistry'):
233 "calibRegistry", calibRegistry,
234 policy,
"calibRegistryPath", calibRoot)
240 "ImageMappingDictionary.paf",
"policy")
241 imgMappingPolicy = pexPolicy.Policy.createPolicy(imgMappingFile,
242 imgMappingFile.getRepositoryPath())
244 "ExposureMappingDictionary.paf",
"policy")
245 expMappingPolicy = pexPolicy.Policy.createPolicy(expMappingFile,
246 expMappingFile.getRepositoryPath())
248 "CalibrationMappingDictionary.paf",
"policy")
249 calMappingPolicy = pexPolicy.Policy.createPolicy(calMappingFile,
250 calMappingFile.getRepositoryPath())
252 "DatasetMappingDictionary.paf",
"policy")
253 dsMappingPolicy = pexPolicy.Policy.createPolicy(dsMappingFile,
254 dsMappingFile.getRepositoryPath())
261 (
"images", imgMappingPolicy, ImageMapping),
262 (
"exposures", expMappingPolicy, ExposureMapping),
263 (
"calibrations", calMappingPolicy, CalibrationMapping),
264 (
"datasets", dsMappingPolicy, DatasetMapping)
267 for name, defPolicy, cls
in mappingList:
268 if policy.exists(name):
269 datasets = policy.getPolicy(name)
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)
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)
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())
309 if name ==
"exposures" or name ==
"images":
310 expFunc =
"map_" + datasetType
311 mdFunc = expFunc +
"_md"
312 bypassFunc =
"bypass_" + datasetType +
"_md"
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:
319 if not hasattr(self,
"query_" + datasetType +
"_md"):
320 setattr(self,
"query_" + datasetType +
"_md",
321 getattr(self,
"query_" + datasetType))
323 subFunc = expFunc +
"_sub"
324 if not hasattr(self, subFunc):
325 def mapSubClosure(dataId, write=False, mapper=self, mapping=mapping):
326 subId = dataId.copy()
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'])
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()
347 return mapping.lookup(format, subId)
348 setattr(self,
"query_" + datasetType +
"_sub", querySubClosure)
353 if policy.exists(
'camera'):
354 cameraDataSubdir = policy.getString(
'camera')
356 os.path.join(repositoryDir, cameraDataSubdir,
"camera.py"))
357 cameraConfig = afwCameraGeom.CameraConfig()
363 if policy.exists(
'defects'):
365 repositoryDir, policy.getString(
'defects'))
366 defectRegistryLocation = os.path.join(
369 Registry.create(defectRegistryLocation)
378 """Look for the given path in the current root or any of its parents
379 by following "_parent" symlinks; return None if it can't be found. A
380 little tricky because the path may be in an alias of the root (e.g.
381 ".") and because the "_parent" links go between the root and the rest
390 while len(rootDir) > 1
and rootDir[-1] ==
'/':
391 rootDir = rootDir[:-1]
393 if path.startswith(rootDir +
"/"):
395 path = path[len(rootDir)+1:]
397 elif rootDir ==
"/" and path.startswith(
"/"):
402 pathPrefix = os.path.dirname(path)
403 while pathPrefix !=
"" and pathPrefix !=
"/":
404 if os.path.realpath(pathPrefix) == os.path.realpath(self.
root):
406 pathPrefix = os.path.dirname(pathPrefix)
407 if os.path.realpath(pathPrefix) != os.path.realpath(self.
root):
409 if os.path.exists(path):
412 if pathPrefix ==
"/":
414 elif pathPrefix !=
"":
415 path = path[len(pathPrefix)+1:]
422 firstBracket = path.find(
"[")
423 if firstBracket != -1:
424 strippedPath = path[:firstBracket]
425 while not os.path.exists(os.path.join(dir, strippedPath)):
426 dir = os.path.join(dir,
"_parent")
427 if not os.path.exists(dir):
429 return os.path.join(dir, path)
432 """Rename any existing object with the given type and dataId.
434 The CameraMapper implementation saves objects in a sequence of e.g.:
438 All of the backups will be placed in the output repo, however, and will
439 not be removed if they are found elsewhere in the _parent chain. This
440 means that the same file will be stored twice if the previous version was
441 found in an input repo.
444 newLocation = self.
map(datasetType, dataId, write=
True)
445 newPath = newLocation.getLocations()[0]
448 while path
is not None:
450 oldPaths.append((n, path))
452 for n, oldPath
in reversed(oldPaths):
453 newDir, newFile = os.path.split(newPath)
454 if not os.path.exists(newDir):
456 shutil.copy(oldPath,
"%s~%d" % (newPath, n))
459 """Return supported keys.
460 @return (iterable) List of keys usable in a dataset identifier"""
461 return self.keyDict.iterkeys()
464 """Return supported keys and their value types for a given dataset
465 type at a given level of the key hierarchy.
467 @param datasetType (str) dataset type or None for all keys
468 @param level (str) level or None for all levels
469 @return (iterable) Set of keys usable in a dataset identifier"""
470 if datasetType
is None:
474 if level
is not None and level
in self.
levels:
475 keyDict = dict(keyDict)
476 for l
in self.
levels[level]:
485 if self.defaultSubLevels.has_key(level):
491 """Return the name of the camera that this CameraMapper is for."""
493 m = re.search(
r'(\w+)Mapper', className)
495 m = re.search(
r"class '[\w.]*?(\w+)'", className)
497 return name[:1].lower() + name[1:]
if name
else ''
501 """Return the name of the EUPS product containing this CameraMapper."""
502 modPath = os.path.realpath(sys.modules[cls.__module__].__file__)
505 for prod
in eups.Eups().findProducts(tags=[
"setup"]):
506 path = os.path.realpath(prod.dir)
507 if modPath.startswith(path)
and len(path) > bestPathLen:
509 bestPathLen = len(path)
511 raise NotImplementedError(
512 "%s did not provide an eups product name, and one could not be discovered." %
517 """Map a camera dataset."""
519 raise RuntimeError(
"No camera dataset available.")
522 pythonType =
"lsst.afw.cameraGeom.CameraConfig",
524 storageName =
"ConfigStorage",
530 """Standardize a camera dataset by converting it to a camera object.
532 @param[in] item: camera info (an lsst.afw.cameraGeom.CameraConfig)
533 @param[in] dataId: data ID dict
536 raise RuntimeError(
"No camera dataset available.")
538 return afwCameraGeom.makeCameraFromPath(
540 ampInfoPath = ampInfoPath,
545 """Map defects dataset.
547 @return a very minimal ButlerLocation containing just the locationList field
548 (just enough information that bypass_defects can use it).
551 if defectFitsPath
is None:
552 raise RuntimeError(
"No defects available for dataId=%s" % (dataId,))
557 """Return a defect based on the butler location returned by map_defects
559 @param[in] butlerLocation: a ButlerLocation with locationList = path to defects FITS file
560 @param[in] dataId: the usual data ID; "ccd" must be set
562 Note: the name "bypass_XXX" means the butler makes no attempt to convert the ButlerLocation
563 into an object, which is what we want for now, since that conversion is a bit tricky.
566 defectsFitsPath = butlerLocation.locationList[0]
567 with pyfits.open(defectsFitsPath)
as hduList:
568 for hdu
in hduList[1:]:
569 if hdu.header[
"name"] != detectorName:
573 for data
in hdu.data:
581 raise RuntimeError(
"No defects for ccd %s in %s" % (detectorName, defectsFitsPath))
584 """Standardize a raw dataset by converting it to an Exposure instead of an Image"""
590 """Map a sky policy."""
592 "Internal",
None,
None)
595 """Standardize a sky policy by returning the one we use."""
605 """Return CCD key and value used to look a defect in the defect registry
607 The default implementation simply returns ("ccd", full detector name)
612 """Set up a registry (usually SQLite3), trying a number of possible
614 @param name (string) Name of registry
615 @param path (string) Path for registry
616 @param policyKey (string) Key in policy for registry path
617 @param root (string) Root directory to look in
618 @return (lsst.daf.butlerUtils.Registry) Registry object"""
620 if path
is None and policy.exists(policyKey):
622 policy.getString(policyKey)).locString()
623 if not os.path.exists(path):
624 if not os.path.isabs(path)
and root
is not None:
627 self.log.log(pexLog.Log.WARN,
628 "Unable to locate registry at policy path (also looked in root): %s" % path)
631 self.log.log(pexLog.Log.WARN,
632 "Unable to locate registry at policy path: %s" % path)
634 if path
is None and root
is not None:
635 path = os.path.join(root,
"%s.sqlite3" % name)
638 self.log.log(pexLog.Log.WARN,
639 "Unable to locate %s registry in root: %s" % (name, path))
642 path = os.path.join(
".",
"%s.sqlite3" % name)
645 self.log.log(pexLog.Log.WARN,
646 "Unable to locate %s registry in current dir: %s" % (name, path))
649 if not os.path.exists(path):
651 if newPath
is not None:
653 self.log.log(pexLog.Log.INFO,
654 "Loading %s registry from %s" % (name, path))
655 registry = Registry.create(path)
657 raise RuntimeError,
"Unable to load %s registry from %s" % (name, path)
661 self.log.log(pexLog.Log.WARN,
662 "No registry loaded; proceeding without one")
666 """Generate a standard ID dict from a camera-specific ID dict.
668 Canonical keys include:
669 - amp: amplifier name
670 - ccd: CCD name (in LSST this is a combination of raft and sensor)
671 The default implementation returns a copy of its input.
673 @param dataId[in] (dict) Dataset identifier; this must not be modified
674 @return (dict) Transformed dataset identifier"""
679 """Convert a template path to an actual path, using the actual data
680 identifier. This implementation is usually sufficient but can be
681 overridden by the subclass.
682 @param template (string) Template path
683 @param actualId (dict) Dataset identifier
684 @return (string) Pathname"""
690 """Convert a CCD name to a form useful as a filename
692 The default implementation converts spaces to underscores.
694 return ccdName.replace(
" ",
"_")
697 """Extract the detector (CCD) name from the dataset identifier.
699 The name in question is the detector name used by lsst.afw.cameraGeom.
701 @param dataId (dict) Dataset identifier
702 @return (string) Detector name
704 raise NotImplementedError(
"No _extractDetectorName() function specified")
707 """Extract the amplifier identifer from a dataset identifier.
709 @warning this is deprecated; DO NOT USE IT
711 amplifier identifier has two parts: the detector name for the CCD
712 containing the amplifier and index of the amplifier in the detector.
713 @param dataId (dict) Dataset identifer
714 @return (tuple) Amplifier identifier"""
717 return (trDataId[
"ccd"], int(trDataId[
'amp']))
720 """Set the detector object in an Exposure for an amplifier.
721 Defects are also added to the Exposure based on the detector object.
722 @param[in,out] item (lsst.afw.image.Exposure)
723 @param dataId (dict) Dataset identifier
724 @param trimmed (bool) Should detector be marked as trimmed? (ignored)"""
729 """Set the detector object in an Exposure for a CCD.
730 @param[in,out] item (lsst.afw.image.Exposure)
731 @param dataId (dict) Dataset identifier
732 @param trimmed (bool) Should detector be marked as trimmed? (ignored)"""
735 detector = self.
camera[detectorName]
736 item.setDetector(detector)
739 """Set the filter object in an Exposure. If the Exposure had a FILTER
740 keyword, this was already processed during load. But if it didn't,
741 use the filter from the registry.
742 @param mapping (lsst.daf.butlerUtils.Mapping)
743 @param[in,out] item (lsst.afw.image.Exposure)
744 @param dataId (dict) Dataset identifier"""
746 if not (isinstance(item, afwImage.ExposureU)
or isinstance(item, afwImage.ExposureI)
or
747 isinstance(item, afwImage.ExposureF)
or isinstance(item, afwImage.ExposureD)):
750 actualId = mapping.need([
'filter'], dataId)
751 filterName = actualId[
'filter']
752 if self.
filters is not None and self.filters.has_key(filterName):
753 filterName = self.
filters[filterName]
757 """Set the exposure time and exposure midpoint in the calib object in
758 an Exposure. Use the EXPTIME and MJD-OBS keywords (and strip out
760 @param mapping (lsst.daf.butlerUtils.Mapping)
761 @param[in,out] item (lsst.afw.image.Exposure)
762 @param dataId (dict) Dataset identifier"""
764 md = item.getMetadata()
765 calib = item.getCalib()
766 if md.exists(
"EXPTIME"):
767 expTime = md.get(
"EXPTIME")
768 calib.setExptime(expTime)
771 expTime = calib.getExptime()
772 if md.exists(
"MJD-OBS"):
774 dafBase.DateTime.MJD, dafBase.DateTime.UTC)
775 obsMidpoint = obsStart.nsecs() + long(expTime * 1000000000L / 2)
782 """Default standardization function for images.
783 @param mapping (lsst.daf.butlerUtils.Mapping)
784 @param[in,out] item (lsst.afw.image.Exposure)
785 @param dataId (dict) Dataset identifier
786 @param filter (bool) Set filter?
787 @param trimmed (bool) Should detector be marked as trimmed?
788 @return (lsst.afw.image.Exposure) the standardized Exposure"""
790 if (re.search(
r'Exposure', mapping.python)
and re.search(
r'Image',mapping.persistable)):
793 if mapping.level.lower() ==
"amp":
795 elif mapping.level.lower() ==
"ccd":
800 if not isinstance(mapping, CalibrationMapping):
806 """Find the defects for a given CCD.
807 @param dataId (dict) Dataset identifier
808 @return (string) path to the defects file or None if not available"""
812 raise RuntimeError,
"No registry for defect lookup"
816 rows = self.registry.executeQuery((
"taiObs",), (
"raw_visit",),
817 [(
"visit",
"?")],
None, (dataId[
'visit'],))
820 assert len(rows) == 1
825 rows = self.defectRegistry.executeQuery((
"path",), (
"defect",),
827 (
"DATETIME(?)",
"DATETIME(validStart)",
"DATETIME(validEnd)"),
829 if not rows
or len(rows) == 0:
832 return os.path.join(self.
defectPath, rows[0][0])
834 raise RuntimeError(
"Querying for defects (%s, %s) returns %d files: %s" %
835 (ccdVal, taiObs, len(rows),
", ".join([_[0]
for _
in rows])))
839 """Generate an exposure from a DecoratedImage or similar
840 @param[in] image Image of interest
841 @return (lsst.afw.image.Exposure) Exposure containing input image
843 if isinstance(image, afwImage.DecoratedImageU)
or isinstance(image, afwImage.DecoratedImageI)
or \
844 isinstance(image, afwImage.DecoratedImageF)
or isinstance(image, afwImage.DecoratedImageD):
848 md = image.getMetadata()
849 exposure.setMetadata(md)
852 wcsMetadata = wcs.getFitsMetadata()
853 for kw
in wcsMetadata.paramNames():
Class for handling dates/times, including MJD, UTC, and TAI.
MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > * makeMaskedImage(typename Image< ImagePixelT >::Ptr image, typename Mask< MaskPixelT >::Ptr mask=typename Mask< MaskPixelT >::Ptr(), typename Image< VariancePixelT >::Ptr variance=typename Image< VariancePixelT >::Ptr())
Encapsulate information about a bad portion of a detector.
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...
def _getCcdKeyVal
Utility functions.
a place to record messages and descriptions of the state of processing.
An integer coordinate rectangle.
Wcs::Ptr makeWcs(coord::Coord const &crval, geom::Point2D const &crpix, double CD11, double CD12, double CD21, double CD22)
Create a Wcs object from crval, crpix, CD, using CD elements (useful from python) ...
Holds an integer identifier for an LSST filter.
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.
Exposure< ImagePixelT, MaskPixelT, VariancePixelT >::Ptr makeExposure(MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > &mimage, boost::shared_ptr< Wcs const > wcs=boost::shared_ptr< Wcs const >())