34 from .forcedPhotImage 
import ForcedPhotImageTask, ForcedPhotImageConfig
    37     from lsst.meas.mosaic 
import applyMosaicResults
    39     applyMosaicResults = 
None    41 __all__ = (
"PerTractCcdDataIdContainer", 
"ForcedPhotCcdConfig", 
"ForcedPhotCcdTask", 
"imageOverlapsTract")
    45     """A data ID container which combines raw data IDs with a tract.    49     Required because we need to add "tract" to the raw data ID keys (defined as    50     whatever we use for ``src``) when no tract is provided (so that the user is    51     not required to know which tracts are spanned by the raw data ID).    53     This subclass of `~lsst.pipe.base.DataIdContainer` assumes that a calexp is    54     being measured using the detection information, a set of reference    55     catalogs, from the set of coadds which intersect with the calexp.  It needs    56     the calexp id (e.g.  visit, raft, sensor), but is also uses the tract to    57     decide what set of coadds to use.  The references from the tract whose    58     patches intersect with the calexp are used.    62         """Make self.refList from self.idList    65             raise RuntimeError(
"Must call setDatasetType first")
    66         log = Log.getLogger(
"meas.base.forcedPhotCcd.PerTractCcdDataIdContainer")
    68         visitTract = collections.defaultdict(set)   
    69         visitRefs = collections.defaultdict(list)   
    71             if "tract" not in dataId:
    73                 log.info(
"Reading WCS for components of dataId=%s to determine tracts", dict(dataId))
    75                     skymap = namespace.butler.get(namespace.config.coaddName + 
"Coadd_skyMap")
    77                 for ref 
in namespace.butler.subset(
"calexp", dataId=dataId):
    78                     if not ref.datasetExists(
"calexp"):
    81                     visit = ref.dataId[
"visit"]
    82                     visitRefs[visit].
append(ref)
    84                     md = ref.get(
"calexp_md", immediate=
True)
    89                     tract = skymap.findTract(wcs.pixelToSky(box.getCenter()))
    91                         visitTract[visit].add(tract.getId())
    93                 self.
refList.extend(ref 
for ref 
in namespace.butler.subset(self.
datasetType, dataId=dataId))
    96         for visit, tractSet 
in visitTract.items():
    97             for ref 
in visitRefs[visit]:
    98                 for tract 
in tractSet:
   100                                                                  dataId=ref.dataId, tract=tract))
   102             tractCounter = collections.Counter()
   103             for tractSet 
in visitTract.values():
   104                 tractCounter.update(tractSet)
   105             log.info(
"Number of visits for each tract: %s", dict(tractCounter))
   109     """Return whether the given bounding box overlaps the tract given a WCS.   113     tract : `lsst.skymap.TractInfo`   114         TractInfo specifying a tract.   115     imageWcs : `lsst.afw.geom.SkyWcs`   116         World coordinate system for the image.   117     imageBox : `lsst.geom.Box2I`   118         Bounding box for the image.   123         `True` if the bounding box overlaps the tract; `False` otherwise.   125     tractPoly = tract.getOuterSkyPolygon()
   129         imageSkyCorners = imageWcs.pixelToSky(imagePixelCorners)
   130     except lsst.pex.exceptions.LsstCppException 
as e:
   132         if (
not isinstance(e.message, lsst.pex.exceptions.DomainErrorException) 
and   133                 not isinstance(e.message, lsst.pex.exceptions.RuntimeErrorException)):
   138     return tractPoly.intersects(imagePoly)  
   144         doc=
"Apply meas_mosaic ubercal results to input calexps?",
   158         self.
exposure.nameTemplate = 
"{inputName}"   159         self.
exposure.dimensions = [
"Instrument", 
"Visit", 
"Detector"]
   160         self.
measCat.nameTemplate = 
"forced_src"   161         self.
measCat.dimensions = [
"Instrument", 
"Visit", 
"Detector", 
"SkyMap", 
"Tract"]
   164                                   "inputCoaddName": 
"deep"})
   165         self.
quantum.dimensions = (
"Instrument", 
"Visit", 
"Detector", 
"SkyMap", 
"Tract")
   169     """A command-line driver for performing forced measurement on CCD images.   173     This task is a subclass of   174     :lsst-task:`lsst.meas.base.forcedPhotImage.ForcedPhotImageTask` which is   175     specifically for doing forced measurement on a single CCD exposure, using   176     as a reference catalog the detections which were made on overlapping   179     The `run` method (inherited from `ForcedPhotImageTask`) takes a   180     `~lsst.daf.persistence.ButlerDataRef` argument that corresponds to a single   181     CCD. This should contain the data ID keys that correspond to the   182     ``forced_src`` dataset (the output dataset for this task), which are   183     typically all those used to specify the ``calexp`` dataset (``visit``,   184     ``raft``, ``sensor`` for LSST data) as well as a coadd tract. The tract is   185     used to look up the appropriate coadd measurement catalogs to use as   186     references (e.g. ``deepCoadd_src``; see   187     :lsst-task:`lsst.meas.base.references.CoaddSrcReferencesTask` for more   188     information). While the tract must be given as part of the dataRef, the   189     patches are determined automatically from the bounding box and WCS of the   190     calexp to be measured, and the filter used to fetch references is set via   191     the ``filter`` option in the configuration of   192     :lsst-task:`lsst.meas.base.references.BaseReferencesTask`).   194     In addition to the `run` method, `ForcedPhotCcdTask` overrides several   195     methods of `ForcedPhotImageTask` to specialize it for single-CCD   196     processing, including `~ForcedPhotImageTask.makeIdFactory`,   197     `~ForcedPhotImageTask.fetchReferences`, and   198     `~ForcedPhotImageTask.getExposure`. None of these should be called   199     directly by the user, though it may be useful to override them further in   203     ConfigClass = ForcedPhotCcdConfig
   205     _DefaultName = 
"forcedPhotCcd"   209         inputData[
'refWcs'] = butler.get(f
"{self.config.refWcs.name}.wcs", inputDataIds[
"refWcs"])
   211                                                     inputData[
'refCat'], inputData[
'refWcs'])
   213                                                     inputData[
'exposure'],
   214                                                     inputData[
'refCat'], inputData[
'refWcs'],
   215                                                     "VisitDetector", butler)
   217         return self.
run(**inputData)
   220         """Filter reference catalog so that all sources are within the   221         boundaries of the exposure.   225         exposure : `lsst.afw.image.exposure.Exposure`   226             Exposure to generate the catalog for.   227         refCat : `lsst.afw.table.SourceCatalog`   228             Catalog of shapes and positions at which to force photometry.   229         refWcs : `lsst.afw.image.SkyWcs`   230             Reference world coordinate system.   234         refSources : `lsst.afw.table.SourceCatalog`   235             Filtered catalog of forced sources to measure.   239         Filtering the reference catalog is currently handled by Gen2   240         specific methods.  To function for Gen3, this method copies   241         code segments to do the filtering and transformation.  The   242         majority of this code is based on the methods of   243         lsst.meas.algorithms.loadReferenceObjects.ReferenceObjectLoader   249         expWcs = exposure.getWcs()
   250         expRegion = exposure.getBBox(lsst.afw.image.PARENT)
   252         expBoxCorners = expBBox.getCorners()
   253         expSkyCorners = [expWcs.pixelToSky(corner).getVector() 
for   254                          corner 
in expBoxCorners]
   259         sources = 
type(refCat)(refCat.table)
   260         for record 
in refCat:
   261             if expPolygon.contains(record.getCoord().getVector()):
   262                 sources.append(record)
   263         refCatIdDict = {ref.getId(): ref.getParent() 
for ref 
in sources}
   268         refSources = 
type(refCat)(refCat.table)
   269         for record 
in refCat:
   270             if expPolygon.contains(record.getCoord().getVector()):
   271                 recordId = record.getId()
   274                     if topId 
in refCatIdDict:
   275                         topId = refCatIdDict[topId]
   279                     refSources.append(record)
   283         for refRecord 
in refSources:
   284             refRecord.setFootprint(refRecord.getFootprint().
transform(refWcs,
   290         """Create an object that generates globally unique source IDs.   292         Source IDs are created based on a per-CCD ID and the ID of the CCD   297         dataRef : `lsst.daf.persistence.ButlerDataRef`   298             Butler data reference. The ``ccdExposureId_bits`` and   299             ``ccdExposureId`` datasets are accessed. The data ID must have the   300             keys that correspond to ``ccdExposureId``, which are generally the   301             same as those that correspond to ``calexp`` (``visit``, ``raft``,   302             ``sensor`` for LSST data).   304         expBits = dataRef.get(
"ccdExposureId_bits")
   305         expId = 
int(dataRef.get(
"ccdExposureId"))
   309         return int(dataRef.get(
"ccdExposureId", immediate=
True))
   312         """Get sources that overlap the exposure.   316         dataRef : `lsst.daf.persistence.ButlerDataRef`   317             Butler data reference corresponding to the image to be measured;   318             should have ``tract``, ``patch``, and ``filter`` keys.   319         exposure : `lsst.afw.image.Exposure`   320             The image to be measured (used only to obtain a WCS and bounding   325         referencs : `lsst.afw.table.SourceCatalog`   326             Catalog of sources that overlap the exposure   330         The returned catalog is sorted by ID and guarantees that all included   331         children have their parent included and that all Footprints are valid.   333         All work is delegated to the references subtask; see   334         :lsst-task:`lsst.meas.base.references.CoaddSrcReferencesTask`   335         for information about the default behavior.   339         unfiltered = self.references.fetchInBox(dataRef, exposure.getBBox(), exposure.getWcs())
   340         for record 
in unfiltered:
   341             if record.getFootprint() 
is None or record.getFootprint().getArea() == 0:
   342                 if record.getParent() != 0:
   343                     self.
log.
warn(
"Skipping reference %s (child of %s) with bad Footprint",
   344                                   record.getId(), record.getParent())
   346                     self.
log.
warn(
"Skipping reference parent %s with bad Footprint", record.getId())
   347                     badParents.add(record.getId())
   348             elif record.getParent() 
not in badParents:
   349                 references.append(record)
   355         """Read input exposure for measurement.   359         dataRef : `lsst.daf.persistence.ButlerDataRef`   360             Butler data reference. Only the ``calexp`` dataset is used, unless   361             ``config.doApplyUberCal`` is `True`, in which case the   362             corresponding meas_mosaic outputs are used as well.   364         exposure = ForcedPhotImageTask.getExposure(self, dataRef)
   365         if not self.
config.doApplyUberCal:
   367         if applyMosaicResults 
is None:
   369                 "Cannot use improved calibrations for %s because meas_mosaic could not be imported."   375     def _getConfigName(self):
   377         return self.
dataPrefix + 
"forcedPhotCcd_config"   379     def _getMetadataName(self):
   381         return self.
dataPrefix + 
"forcedPhotCcd_metadata"   384     def _makeArgumentParser(cls):
   386         parser.add_id_argument(
"--id", 
"forced_src", help=
"data ID with raw CCD keys [+ tract optionally], "   387                                "e.g. --id visit=12345 ccd=1,2 [tract=0]",
   388                                ContainerClass=PerTractCcdDataIdContainer)
 
def getExposure(self, dataRef)
A floating-point coordinate rectangle geometry. 
def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler)
def makeDataRefList(self, namespace)
std::shared_ptr< FrameSet > append(FrameSet const &first, FrameSet const &second)
Construct a FrameSet that performs two transformations in series. 
def formatTemplateNames(self, templateParamsDict)
daf::base::PropertySet * set
def run(self, measCat, exposure, refCat, refWcs, exposureId=None)
def makeIdFactory(self, dataRef)
static std::shared_ptr< IdFactory > makeSource(RecordId expId, int reserved)
Return an IdFactory that includes another, fixed ID in the higher-order bits. 
static ConvexPolygon convexHull(std::vector< UnitVector3d > const &points)
convexHull returns the convex hull of the given set of points if it exists and throws an exception ot...
def generateMeasCat(self, exposureDataId, exposure, refCat, refWcs, idPackerName, butler)
def imageOverlapsTract(tract, imageWcs, imageBox)
ConvexPolygon is a closed convex polygon on the unit sphere. 
def getExposureId(self, dataRef)
std::shared_ptr< SkyWcs > makeSkyWcs(TransformPoint2ToPoint2 const &pixelsToFieldAngle, lsst::geom::Angle const &orientation, bool flipX, lsst::geom::SpherePoint const &boresight, std::string const &projection="TAN")
Construct a FITS SkyWcs from camera geometry. 
def filterReferences(self, exposure, refCat, refWcs)
static Key< RecordId > getParentKey()
Key for the parent ID. 
def fetchReferences(self, dataRef, exposure)
lsst::geom::Box2I bboxFromMetadata(daf::base::PropertySet &metadata)
Determine the image bounding box from its metadata (FITS header)