Coverage for python/lsst/obs/hsc/hscMapper.py : 44%

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
"""Provides abstract-physical mapping for HSC data"""
def addFilters(cls): # SDSS g': http://www.naoj.org/Observing/Instruments/SCam/txt/g.txt # SDSS r': http://www.naoj.org/Observing/Instruments/SCam/txt/r.txt # SDSS i': http://www.naoj.org/Observing/Instruments/SCam/txt/i.txt # SDSS z': http://www.naoj.org/Observing/Instruments/SCam/txt/z.txt # y-band: Shimasaku et al., 2005, PASJ, 57, 447
# The order of these defineFilter commands matters as their IDs are used to generate at least some # object IDs (e.g. on coadds) and changing the order will invalidate old objIDs
alias=["NONE", "None", "Unrecognised", "UNRECOGNISED", "Unrecognized", "UNRECOGNIZED", "NOTSET", ])
try: kwargs['root'] = os.path.join(os.environ.get('SUPRIME_DATA_DIR'), 'HSC') except Exception: raise RuntimeError("Either $SUPRIME_DATA_DIR or root= must be specified") calibSearch = [os.path.join(kwargs['root'], 'CALIB')] if "repositoryCfg" in kwargs: calibSearch += [os.path.join(cfg.root, 'CALIB') for cfg in kwargs["repositoryCfg"].parents if hasattr(cfg, "root")] calibSearch += [cfg.root for cfg in kwargs["repositoryCfg"].parents if hasattr(cfg, "root")] for calibRoot in calibSearch: if os.path.exists(os.path.join(calibRoot, "calibRegistry.sqlite3")): kwargs['calibRoot'] = calibRoot break if not kwargs.get('calibRoot', None): lsst.log.Log.getLogger("HscMapper").warn("Unable to find calib root directory")
# Ensure each dataset type of interest knows about the full range of keys available from the registry 'visit': int, 'filter': str, 'ccd': int, 'dateObs': str, 'taiObs': str, 'expTime': float, 'pointing': int, } # processCcd outputs "postISRCCD", "calexp", "postISRCCD", "src", "icSrc", "icMatch", "srcMatch", # mosaic outputs "wcs", "fcr", # processCcd QA "ossThumb", "flattenedThumb", "calexpThumb", "plotMagHist", "plotSeeingRough", "plotSeeingRobust", "plotSeeingMap", "plotEllipseMap", "plotEllipticityMap", "plotFwhmGrid", "plotEllipseGrid", "plotEllipticityGrid", "plotPsfSrcGrid", "plotPsfModelGrid", "fitsFwhmGrid", "fitsEllipticityGrid", "fitsEllPaGrid", "fitsPsfSrcGrid", "fitsPsfModelGrid", "tableSeeingMap", "tableSeeingGrid", # forcedPhot outputs "forced_src", ):
# # self.filters is used elsewhere, and for now we'll set it # # It's a bit hard to initialise self.filters properly until #2113 is resolved, # including the part that makes it possible to get all aliases # "HSC-G", "HSC-R", "HSC-R2", "HSC-I", "HSC-I2", "HSC-Z", "HSC-Y", "ENG-R1", "NB0387", "NB0468", "NB0515", "NB0527", "NB0656", "NB0718", "NB0816", "NB0921", "NB0926", "IB0945", "NB0973", "NB1010", "SH", "PH", "NONE", "UNRECOGNISED"]:
# # The number of bits allocated for fields in object IDs, appropriate for # the default-configured Rings skymap. # # This shouldn't be the mapper's job at all; see #2797.
raise RuntimeError("You have more filters defined than fit into the %d bits allocated" % HscMapper._nbit_filter)
"""Make the camera object
This implementation layers a cache over the parent class' implementation. Caching the camera improves the instantiation time for the HscMapper because parsing the camera's Config involves a lot of 'stat' calls (through the tracebacks). """
def clearCache(cls): """Clear the camera cache
This is principally intended to help memory leak tests pass. """
"""Need to strip 'flags' argument from map
We want the 'flags' argument passed to the butler to work (it's used to change how the reading/writing is done), but want it removed from the mapper (because it doesn't correspond to a registry column). """ copyId = dataId.copy() copyId.pop("flags", None) location = super(HscMapper, self).map(datasetType, copyId, write=write)
if 'flags' in dataId: location.getAdditionalData().set('flags', dataId['flags'])
return location
"""Flip the chip left/right or top/bottom. Process either/and the pixels and wcs
Most chips are flipped L/R, but the rotated ones (100..103) are flipped T/B """ flipLR, flipTB = (False, True) if dataId['ccd'] in (100, 101, 102, 103) else (True, False) if exp: exp.setMaskedImage(afwMath.flipImage(exp.getMaskedImage(), flipLR, flipTB)) if wcs: ampDimensions = exp.getDimensions() if dims is None else dims ampCenter = afwGeom.Point2D(ampDimensions/2.0) wcs = afwGeom.makeFlippedWcs(wcs, flipLR, flipTB, ampCenter)
return exp, wcs
if False: # no std_raw_md in baseclass md = super(HscMapper, self).std_raw_md(md, dataId) # not present in baseclass # # We need to flip the WCS defined by the metadata in case anyone ever constructs a Wcs from it # wcs = afwGeom.makeSkyWcs(md) wcs = self._flipChipsLR(None, wcs, dataId, dims=afwImage.bboxFromMetadata(md).getDimensions())[1] wcsR = afwGeom.makeSkyWcs(crpix=wcs.getPixelOrigin(), crval=wcs.getSkyOrigin(), cdMatrix=wcs.getCdMatrix()*0.992) wcsMd = wcsR.getFitsMetadata()
for k in wcsMd.names(): md.set(k, wcsMd.get(k))
return md
exp = super(HscMapper, self).std_raw(item, dataId) exp, wcs = self._flipChipsLR(exp, exp.getWcs(), dataId) exp.setWcs(wcs) return exp
exposure = self._standardizeExposure(self.calibrations['dark'], item, dataId, trimmed=False) visitInfo = afwImage.VisitInfo(exposureTime=1.0, darkTime=1.0) exposure.getInfo().setVisitInfo(visitInfo) return exposure
return (self._extractDetectorName(dataId), 0, 0)
return int("%(ccd)d" % dataId)
"""Compute the 64-bit (long) identifier for a CCD exposure.
@param dataId (dict) Data identifier with visit, ccd """ pathId = self._transformId(dataId) visit = pathId['visit'] ccd = pathId['ccd'] return visit*200 + ccd
return self._computeCcdExposureId(dataId)
"""How many bits are required for the maximum exposure ID""" return 32 # just a guess, but this leaves plenty of space for sources
"""Map a linearizer.""" if self._linearize is None: raise RuntimeError("No linearizer available.") actualId = self._transformId(dataId) return ButlerLocation( pythonType="lsst.ip.isr.LinearizeSquared", cppType="Config", storageName="PickleStorage", locationList="ignored", dataId=actualId, mapper=self, storage=self.rootStorage)
"""Return the linearizer. """ if self._linearize is None: raise RuntimeError("No linearizer available.") return self._linearize
"""Compute the 64-bit (long) identifier for a coadd.
@param dataId (dict) Data identifier with tract and patch. @param singleFilter (bool) True means the desired ID is for a single- filter coadd, in which case dataId must contain filter. """
tract = int(dataId['tract']) if tract < 0 or tract >= 2**HscMapper._nbit_tract: raise RuntimeError('tract not in range [0,%d)' % (2**HscMapper._nbit_tract)) patchX, patchY = [int(patch) for patch in dataId['patch'].split(',')] for p in (patchX, patchY): if p < 0 or p >= 2**HscMapper._nbit_patch: raise RuntimeError('patch component not in range [0, %d)' % 2**HscMapper._nbit_patch) oid = (((tract << HscMapper._nbit_patch) + patchX) << HscMapper._nbit_patch) + patchY if singleFilter: return (oid << HscMapper._nbit_filter) + afwImage.Filter(dataId['filter']).getId() return oid
"""The number of bits used up for patch ID bits""" return 64 - HscMapper._nbit_id
return self._computeCoaddExposureId(dataId, True)
"""The number of bits used up for patch ID bits""" return 64 - HscMapper._nbit_id
return self._computeCoaddExposureId(dataId, False)
# The following allow grabbing a 'psf' from the butler directly, without having to get it from a calexp if write: raise RuntimeError("Writing a psf directly is no longer permitted: write as part of a calexp") copyId = dataId.copy() copyId['bbox'] = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1, 1)) return self.map_calexp_sub(copyId)
return calexp.getPsf()
def getCameraName(cls): return "hsc" |