def readRawAmps(fileName, detector): """Given a file name read the amps and attach the detector. Parameters ---------- fileName : `str` The full path to a file containing data from a single CCD. detector : `lsst.afw.cameraGeom.Detector` Detector to associate with the amps. Returns ------- ampExps : `list` of `lsst.afw.image.Exposure` All the individual amps read from the file. """ amps = [] for hdu in range(1, len(detector)+1): reader = afwImage.ImageFitsReader(fileName, hdu=hdu) exp = afwImage.makeExposure(afwImage.makeMaskedImage(reader.read(dtype=np.dtype(np.int32), allowUnsafe=True))) exp.setDetector(detector) exp.setMetadata(reader.readMetadata()) amps.append(exp) return amps
def readFitsWithOptions(filename, stamp_factory, options): """Read stamps from FITS file, allowing for only a subregion of the stamps to be read. Parameters ---------- filename : `str` A string indicating the file to read stamp_factory : classmethod A factory function defined on a dataclass for constructing stamp objects a la `lsst.meas.alrogithm.Stamp` options : `PropertyList` or `dict` A collection of parameters. If it contains a bounding box (``bbox`` key), or if certain other keys (``llcX``, ``llcY``, ``width``, ``height``) are available for one to be constructed, the bounding box is passed to the ``FitsReader`` in order to return a sub-image. Returns ------- stamps : `list` of dataclass objects like `Stamp`, PropertyList A tuple of a list of `Stamp`-like objects metadata : `PropertyList` The metadata """ # extract necessary info from metadata metadata = afwFits.readMetadata(filename, hdu=0) nStamps = metadata["N_STAMPS"] has_archive = metadata["HAS_ARCHIVE"] if has_archive: archive_ids = metadata.getArray("ARCHIVE_IDS") with afwFits.Fits(filename, 'r') as f: nExtensions = f.countHdus() # check if a bbox was provided kwargs = {} if options: # gen3 API if "bbox" in options.keys(): kwargs["bbox"] = options["bbox"] # gen2 API elif "llcX" in options.keys(): llcX = options["llcX"] llcY = options["llcY"] width = options["width"] height = options["height"] bbox = Box2I(Point2I(llcX, llcY), Extent2I(width, height)) kwargs["bbox"] = bbox stamp_parts = {} # We need to be careful because nExtensions includes the primary # header data unit for idx in range(nExtensions - 1): md = afwFits.readMetadata(filename, hdu=idx + 1) if md['EXTNAME'] in ('IMAGE', 'VARIANCE'): reader = afwImage.ImageFitsReader(filename, hdu=idx + 1) elif md['EXTNAME'] == 'MASK': reader = afwImage.MaskFitsReader(filename, hdu=idx + 1) elif md['EXTNAME'] == 'ARCHIVE_INDEX': f.setHdu(idx + 1) archive = afwTable.io.InputArchive.readFits(f) continue elif md['EXTTYPE'] == 'ARCHIVE_DATA': continue else: raise ValueError(f"Unknown extension type: {md['EXTNAME']}") stamp_parts.setdefault( md['EXTVER'], {})[md['EXTNAME'].lower()] = reader.read(**kwargs) if len(stamp_parts) != nStamps: raise ValueError( f'Number of stamps read ({len(stamp_parts)}) does not agree with the ' f'number of stamps recorded in the metadata ({nStamps}).') # construct stamps themselves stamps = [] for k in range(nStamps): # Need to increment by one since EXTVER starts at 1 maskedImage = afwImage.MaskedImageF(**stamp_parts[k + 1]) archive_element = archive.get(archive_ids[k]) if has_archive else None stamps.append(stamp_factory(maskedImage, metadata, k, archive_element)) return stamps, metadata
def readFitsWithOptions(filename, stamp_factory, options): """Read stamps from FITS file, allowing for only a subregion of the stamps to be read. Parameters ---------- filename : `str` A string indicating the file to read stamp_factory : classmethod A factory function defined on a dataclass for constructing stamp objects a la `lsst.meas.alrogithm.Stamp` options : `PropertyList` A collection of parameters. If certain keys are available (``llcX``, ``llcY``, ``width``, ``height``), a bounding box is constructed and passed to the ``FitsReader`` in order to return a sub-image. Returns ------- stamps : `list` of dataclass objects like `Stamp`, PropertyList A tuple of a list of `Stamp`-like objects metadata : `PropertyList` The metadata """ # extract necessary info from metadata metadata = afwFits.readMetadata(filename, hdu=0) f = afwFits.Fits(filename, 'r') nExtensions = f.countHdus() nStamps = metadata["N_STAMPS"] # check if a bbox was provided kwargs = {} if options and options.exists("llcX"): llcX = options["llcX"] llcY = options["llcY"] width = options["width"] height = options["height"] bbox = Box2I(Point2I(llcX, llcY), Extent2I(width, height)) kwargs["bbox"] = bbox stamp_parts = {} # We need to be careful because nExtensions includes the primary # header data unit for idx in range(nExtensions - 1): md = afwFits.readMetadata(filename, hdu=idx + 1) if md['EXTNAME'] in ('IMAGE', 'VARIANCE'): reader = afwImage.ImageFitsReader(filename, hdu=idx + 1) elif md['EXTNAME'] == 'MASK': reader = afwImage.MaskFitsReader(filename, hdu=idx + 1) else: raise ValueError(f"Unknown extension type: {md['EXTNAME']}") stamp_parts.setdefault( md['EXTVER'], {})[md['EXTNAME'].lower()] = reader.read(**kwargs) if len(stamp_parts) != nStamps: raise ValueError( f'Number of stamps read ({len(stamp_parts)}) does not agree with the ' f'number of stamps recorded in the metadata ({nStamps}).') # construct stamps themselves stamps = [] for k in range(nStamps): # Need to increment by one since EXTVER starts at 1 maskedImage = afwImage.MaskedImageF(**stamp_parts[k + 1]) stamps.append(stamp_factory(maskedImage, metadata, k)) return stamps, metadata
def readFits(fileName, hdu=0, flags=0): """Read our list of Backgrounds from a file. Parameters ---------- fileName : `str` FITS file to read hdu : `int` First Header/Data Unit to attempt to read from flags : `int` Flags to control details of reading; currently unused, but present for consistency with `lsst.afw.table.BaseCatalog.readFits`. See Also -------- getImage() """ if not isinstance(fileName, MemFileManager) and not os.path.exists(fileName): raise RuntimeError(f"File not found: {fileName}") self = BackgroundList() f = Fits(fileName, 'r') nHdus = f.countHdus() f.closeFile() if nHdus % 3 != 0: raise RuntimeError(f"BackgroundList FITS file {fileName} has {nHdus} HDUs;" f"expected a multiple of 3 (compression is not supported).") for hdu in range(0, nHdus, 3): # It seems like we ought to be able to just use # MaskedImageFitsReader here, but it warns about EXTTYPE and still # doesn't work quite naturally when starting from a nonzero HDU. imageReader = afwImage.ImageFitsReader(fileName, hdu=hdu) maskReader = afwImage.MaskFitsReader(fileName, hdu=hdu + 1) varianceReader = afwImage.ImageFitsReader(fileName, hdu=hdu + 2) statsImage = afwImage.MaskedImageF(imageReader.read(), maskReader.read(), varianceReader.read()) md = imageReader.readMetadata() x0 = md["BKGD_X0"] y0 = md["BKGD_Y0"] width = md["BKGD_WIDTH"] height = md["BKGD_HEIGHT"] imageBBox = lsst.geom.BoxI(lsst.geom.PointI(x0, y0), lsst.geom.ExtentI(width, height)) interpStyle = afwMath.Interpolate.Style(md["INTERPSTYLE"]) undersampleStyle = afwMath.UndersampleStyle(md["UNDERSAMPLESTYLE"]) # Older outputs won't have APPROX* settings. Provide alternative defaults. # Note: Currently X- and Y-orders must be equal due to a limitation in # math::Chebyshev1Function2. Setting approxOrderY = -1 is equivalent # to saying approxOrderY = approxOrderX. approxStyle = md.get("APPROXSTYLE", afwMath.ApproximateControl.UNKNOWN) approxStyle = afwMath.ApproximateControl.Style(approxStyle) approxOrderX = md.get("APPROXORDERX", 1) approxOrderY = md.get("APPROXORDERY", -1) approxWeighting = md.get("APPROXWEIGHTING", True) bkgd = afwMath.BackgroundMI(imageBBox, statsImage) bctrl = bkgd.getBackgroundControl() # TODO: DM-22814: remove this after v20. # Still needed until then because other code might call the old-style getImageF. with suppress_deprecations(): bctrl.setInterpStyle(interpStyle) bctrl.setUndersampleStyle(undersampleStyle) actrl = afwMath.ApproximateControl(approxStyle, approxOrderX, approxOrderY, approxWeighting) bctrl.setApproximateControl(actrl) bgInfo = (bkgd, interpStyle, undersampleStyle, approxStyle, approxOrderX, approxOrderY, approxWeighting) self.append(bgInfo) return self