Exemplo n.º 1
0
    def read_fits(cls, filename):
        """Build an instance of this class from a file.

        Parameters
        ----------
        filename : `str`
            Name of the file to read.
        """
        # Extract info from metadata.
        global_metadata = afwFits.readMetadata(filename, hdu=0)
        has_default = global_metadata.getBool("HAS_DEFAULT")
        if global_metadata.getBool("HAS_REGIONS"):
            focal_plane_region_names = global_metadata.getArray("REGION_NAMES")
        else:
            focal_plane_region_names = []
        f = afwFits.Fits(filename, "r")
        n_extensions = f.countHdus()
        extended_psf_parts = {}
        for j in range(1, n_extensions):
            md = afwFits.readMetadata(filename, hdu=j)
            if has_default and md["REGION"] == "DEFAULT":
                if md["EXTNAME"] == "IMAGE":
                    default_image = afwImage.ImageF(filename, hdu=j)
                elif md["EXTNAME"] == "MASK":
                    default_mask = afwImage.MaskX(filename, hdu=j)
                continue
            if md["EXTNAME"] == "IMAGE":
                extended_psf_part = afwImage.ImageF(filename, hdu=j)
            elif md["EXTNAME"] == "MASK":
                extended_psf_part = afwImage.MaskX(filename, hdu=j)
            extended_psf_parts.setdefault(
                md["REGION"], {})[md["EXTNAME"].lower()] = extended_psf_part
        # Handle default if present.
        if has_default:
            extended_psf = cls(
                afwImage.MaskedImageF(default_image, default_mask))
        else:
            extended_psf = cls()
        # Ensure we recovered an extended PSF for all focal plane regions.
        if len(extended_psf_parts) != len(focal_plane_region_names):
            raise ValueError(
                f"Number of per-region extended PSFs read ({len(extended_psf_parts)}) does not "
                "match with the number of regions recorded in the metadata "
                f"({len(focal_plane_region_names)}).")
        # Generate extended PSF regions mappings.
        for r_name in focal_plane_region_names:
            extended_psf_image = afwImage.MaskedImageF(
                **extended_psf_parts[r_name])
            detector_list = global_metadata.getArray(r_name)
            extended_psf.add_regional_extended_psf(extended_psf_image, r_name,
                                                   detector_list)
        # Instantiate ExtendedPsf.
        return extended_psf
Exemplo n.º 2
0
    def write_fits(self, filename):
        """Write this object to a file.

        Parameters
        ----------
        filename : `str`
            Name of file to write.
        """
        # Create primary HDU with global metadata.
        metadata = PropertyList()
        metadata["HAS_DEFAULT"] = self.default_extended_psf is not None
        if self.focal_plane_regions:
            metadata["HAS_REGIONS"] = True
            metadata["REGION_NAMES"] = list(self.focal_plane_regions.keys())
            for region, e_psf_region in self.focal_plane_regions.items():
                metadata[region] = e_psf_region.detector_list
        else:
            metadata["HAS_REGIONS"] = False
        fits_primary = afwFits.Fits(filename, "w")
        fits_primary.createEmpty()
        fits_primary.writeMetadata(metadata)
        fits_primary.closeFile()
        # Write default extended PSF.
        if self.default_extended_psf is not None:
            default_hdu_metadata = PropertyList()
            default_hdu_metadata.update({
                "REGION": "DEFAULT",
                "EXTNAME": "IMAGE"
            })
            self.default_extended_psf.image.writeFits(
                filename, metadata=default_hdu_metadata, mode="a")
            default_hdu_metadata.update({
                "REGION": "DEFAULT",
                "EXTNAME": "MASK"
            })
            self.default_extended_psf.mask.writeFits(
                filename, metadata=default_hdu_metadata, mode="a")
        # Write extended PSF for each focal plane region.
        for j, (region,
                e_psf_region) in enumerate(self.focal_plane_regions.items()):
            metadata = PropertyList()
            metadata.update({"REGION": region, "EXTNAME": "IMAGE"})
            e_psf_region.extended_psf_image.image.writeFits(filename,
                                                            metadata=metadata,
                                                            mode="a")
            metadata.update({"REGION": region, "EXTNAME": "MASK"})
            e_psf_region.extended_psf_image.mask.writeFits(filename,
                                                           metadata=metadata,
                                                           mode="a")
Exemplo n.º 3
0
def writeFits(filename, stamp_ims, metadata, write_mask, write_variance):
    """Write a single FITS file containing all stamps.

    Parameters
    ----------
    filename : `str`
        A string indicating the output filename
    stamps_ims : iterable of `lsst.afw.image.MaskedImageF`
        An iterable of masked images
    metadata : `PropertyList`
        A collection of key, value metadata pairs to be
        written to the primary header
    write_mask : `bool`
        Write the mask data to the output file?
    write_variance : `bool`
        Write the variance data to the output file?
    """
    metadata['HAS_MASK'] = write_mask
    metadata['HAS_VARIANCE'] = write_variance
    metadata['N_STAMPS'] = len(stamp_ims)
    # create primary HDU with global metadata
    fitsPrimary = afwFits.Fits(filename, "w")
    fitsPrimary.createEmpty()
    fitsPrimary.writeMetadata(metadata)
    fitsPrimary.closeFile()

    # add all pixel data optionally writing mask and variance information
    for i, stamp in enumerate(stamp_ims):
        metadata = PropertyList()
        # EXTVER should be 1-based, the index from enumerate is 0-based
        metadata.update({'EXTVER': i + 1, 'EXTNAME': 'IMAGE'})
        stamp.getImage().writeFits(filename, metadata=metadata, mode='a')
        if write_mask:
            metadata = PropertyList()
            metadata.update({'EXTVER': i + 1, 'EXTNAME': 'MASK'})
            stamp.getMask().writeFits(filename, metadata=metadata, mode='a')
        if write_variance:
            metadata = PropertyList()
            metadata.update({'EXTVER': i + 1, 'EXTNAME': 'VARIANCE'})
            stamp.getVariance().writeFits(filename,
                                          metadata=metadata,
                                          mode='a')
    return None
Exemplo n.º 4
0
def writeFits(filename,
              stamps,
              metadata,
              type_name,
              write_mask,
              write_variance,
              write_archive=False):
    """Write a single FITS file containing all stamps.

    Parameters
    ----------
    filename : `str`
        A string indicating the output filename
    stamps : iterable of `BaseStamp`
        An iterable of Stamp objects
    metadata : `PropertyList`
        A collection of key, value metadata pairs to be
        written to the primary header
    type_name : `str`
        Python type name of the StampsBase subclass to use
    write_mask : `bool`
        Write the mask data to the output file?
    write_variance : `bool`
        Write the variance data to the output file?
    write_archive : `bool`, optional
        Write an archive to store Persistables along with each stamp?
        Default: ``False``.
    """
    metadata['HAS_MASK'] = write_mask
    metadata['HAS_VARIANCE'] = write_variance
    metadata['HAS_ARCHIVE'] = write_archive
    metadata['N_STAMPS'] = len(stamps)
    metadata['STAMPCLS'] = type_name
    # Record version number in case of future code changes
    metadata['VERSION'] = 1
    # create primary HDU with global metadata
    fitsFile = afwFits.Fits(filename, "w")
    fitsFile.createEmpty()
    # Store Persistables in an OutputArchive and write it
    if write_archive:
        oa = afwTable.io.OutputArchive()
        archive_ids = [oa.put(stamp.archive_element) for stamp in stamps]
        metadata["ARCHIVE_IDS"] = archive_ids
        fitsFile.writeMetadata(metadata)
        oa.writeFits(fitsFile)
    else:
        fitsFile.writeMetadata(metadata)
    fitsFile.closeFile()
    # add all pixel data optionally writing mask and variance information
    for i, stamp in enumerate(stamps):
        metadata = PropertyList()
        # EXTVER should be 1-based, the index from enumerate is 0-based
        metadata.update({'EXTVER': i + 1, 'EXTNAME': 'IMAGE'})
        stamp.stamp_im.getImage().writeFits(filename,
                                            metadata=metadata,
                                            mode='a')
        if write_mask:
            metadata = PropertyList()
            metadata.update({'EXTVER': i + 1, 'EXTNAME': 'MASK'})
            stamp.stamp_im.getMask().writeFits(filename,
                                               metadata=metadata,
                                               mode='a')
        if write_variance:
            metadata = PropertyList()
            metadata.update({'EXTVER': i + 1, 'EXTNAME': 'VARIANCE'})
            stamp.stamp_im.getVariance().writeFits(filename,
                                                   metadata=metadata,
                                                   mode='a')
    return None
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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