Example #1
0
    def testCD_PC(self):
        """Test that we can read a FITS file with both CD and PC keys (like early Suprimecam files)"""
        md = PropertyList()
        for k, v in (
            ("EQUINOX", 2000.0),
            ("RADESYS", "ICRS"),
            ("CRPIX1", 5353.0),
            ("CRPIX2", -35.0),
            ("CD1_1", 0.0),
            ("CD1_2", -5.611E-05),
            ("CD2_1", -5.611E-05),
            ("CD2_2", -0.0),
            ("CRVAL1", 4.5789875),
            ("CRVAL2", 16.30004444),
            ("CUNIT1", "deg"),
            ("CUNIT2", "deg"),
            ("CTYPE1", "RA---TAN"),
            ("CTYPE2", "DEC--TAN"),
            ("CDELT1", -5.611E-05),
            ("CDELT2", 5.611E-05),
        ):
            md.set(k, v)

        wcs = makeSkyWcs(md, strip=False)

        pixPos = Point2D(1000, 2000)
        pred_skyPos = SpherePoint(4.459815023498577 * degrees,
                                  16.544199850984768 * degrees)

        skyPos = wcs.pixelToSky(pixPos)
        self.assertSpherePointsAlmostEqual(skyPos, pred_skyPos)

        for badPC in (False, True):
            for k, v in (
                ("PC001001", 0.0),
                ("PC001002", -1.0 if badPC else 1.0),
                ("PC002001", 1.0 if badPC else -1.0),
                ("PC002002", 0.0),
            ):
                md.set(k, v)

            # Check Greisen and Calabretta A&A 395 1061 (2002), Eq. 3
            if not badPC:
                for i in (
                        1,
                        2,
                ):
                    for j in (
                            1,
                            2,
                    ):
                        self.assertEqual(
                            md.get("CD%d_%d" % (i, j)),
                            md.get("CDELT%d" % i) * md.get("PC00%d00%d" %
                                                           (i, j)))

            wcs2 = makeSkyWcs(md, strip=False)
            skyPos2 = wcs2.pixelToSky(pixPos)
            self.assertSpherePointsAlmostEqual(skyPos2, pred_skyPos)
def makeDiaSources(nSources, diaObjectIds, exposure):
    """Make a test set of DiaSources.

    Parameters
    ----------
    nSources : `int`
        Number of sources to create.
    diaObjectIds : `numpy.ndarray`
        Integer Ids of diaobjects to "associate" with the DiaSources.
    exposure : `lsst.afw.image.Exposure`
        Exposure to create sources over.
    pixelator : `lsst.sphgeom.HtmPixelization`
        Object to compute spatial indicies from.

    Returns
    -------
    diaSources : `pandas.DataFrame`
        DiaSources generated across the exposure.
    """
    bbox = geom.Box2D(exposure.getBBox())
    rand_x = np.random.uniform(bbox.getMinX(), bbox.getMaxX(), size=nSources)
    rand_y = np.random.uniform(bbox.getMinY(), bbox.getMaxY(), size=nSources)

    midPointTaiMJD = exposure.getInfo().getVisitInfo().getDate().get(
        system=dafBase.DateTime.MJD)

    wcs = exposure.getWcs()
    ccdVisitId = exposure.getInfo().getVisitInfo().getExposureId()

    data = []
    for idx, (x, y) in enumerate(zip(rand_x, rand_y)):
        coord = wcs.pixelToSky(x, y)
        htmIdx = 1
        objId = diaObjectIds[idx % len(diaObjectIds)]
        # Put together the minimum values for the alert.
        data.append({
            "ra": coord.getRa().asDegrees(),
            "decl": coord.getDec().asDegrees(),
            "x": x,
            "y": y,
            "ccdVisitId": ccdVisitId,
            "diaObjectId": objId,
            "ssObjectId": 0,
            "parentDiaSourceId": 0,
            "prv_procOrder": 0,
            "diaSourceId": idx,
            "pixelId": htmIdx,
            "midPointTai": midPointTaiMJD + 1.0 * idx,
            # TODO DM-27170: fix this [0] workaround which gets a
            # single character representation of the band.
            "filterName": exposure.getFilter().getCanonicalName()[0],
            "filterId": 0,
            "psNdata": 0,
            "trailNdata": 0,
            "dipNdata": 0,
            "flags": 1
        })

    return pd.DataFrame(data=data)
Example #3
0
def makeDiaSources(nSources, diaObjectIds, exposure):
    """Make a test set of DiaSources.

    Parameters
    ----------
    nSources : `int`
        Number of sources to create.
    diaObjectIds : `numpy.ndarray`
        Integer Ids of diaobjects to "associate" with the DiaSources.
    exposure : `lsst.afw.image.Exposure`
        Exposure to create sources over.

    Returns
    -------
    diaSources : `pandas.DataFrame`
        DiaSources generated across the exposure.
    """
    bbox = geom.Box2D(exposure.getBBox())
    rand_x = np.random.uniform(bbox.getMinX(), bbox.getMaxX(), size=nSources)
    rand_y = np.random.uniform(bbox.getMinY(), bbox.getMaxY(), size=nSources)

    midPointTaiMJD = exposure.getInfo().getVisitInfo().getDate().get(
        system=dafBase.DateTime.MJD)

    wcs = exposure.getWcs()
    ccdVisitId = exposure.info.id

    data = []
    for idx, (x, y) in enumerate(zip(rand_x, rand_y)):
        coord = wcs.pixelToSky(x, y)
        objId = diaObjectIds[idx % len(diaObjectIds)]
        # Put together the minimum values for the alert.
        data.append({
            "ra": coord.getRa().asDegrees(),
            "decl": coord.getDec().asDegrees(),
            "x": x,
            "y": y,
            "ccdVisitId": ccdVisitId,
            "diaObjectId": objId,
            "ssObjectId": 0,
            "parentDiaSourceId": 0,
            "prv_procOrder": 0,
            "diaSourceId": idx + 1,
            "midPointTai": midPointTaiMJD + 1.0 * idx,
            "filterName": exposure.getFilter().bandLabel,
            "psNdata": 0,
            "trailNdata": 0,
            "dipNdata": 0,
            "flags": 1
        })

    return pd.DataFrame(data=data)
def makeDiaObjects(nObjects, exposure):
    """Make a test set of DiaObjects.

    Parameters
    ----------
    nObjects : `int`
        Number of objects to create.
    exposure : `lsst.afw.image.Exposure`
        Exposure to create objects over.

    Returns
    -------
    diaObjects : `pandas.DataFrame`
        DiaObjects generated across the exposure.
    """
    bbox = geom.Box2D(exposure.getBBox())
    rand_x = np.random.uniform(bbox.getMinX(), bbox.getMaxX(), size=nObjects)
    rand_y = np.random.uniform(bbox.getMinY(), bbox.getMaxY(), size=nObjects)

    midPointTaiMJD = exposure.getInfo().getVisitInfo().getDate().get(
        system=dafBase.DateTime.MJD)

    wcs = exposure.getWcs()

    data = []
    for idx, (x, y) in enumerate(zip(rand_x, rand_y)):
        coord = wcs.pixelToSky(x, y)
        htmIdx = 1
        newObject = {
            "ra": coord.getRa().asDegrees(),
            "decl": coord.getDec().asDegrees(),
            "radecTai": midPointTaiMJD,
            "diaObjectId": idx,
            "pixelId": htmIdx,
            "pmParallaxNdata": 0,
            "nearbyObj1": 0,
            "nearbyObj2": 0,
            "nearbyObj3": 0,
            "flags": 1,
            "nDiaSources": 5
        }
        for f in ["u", "g", "r", "i", "z", "y"]:
            newObject["%sPSFluxNdata" % f] = 0
        data.append(newObject)

    return pd.DataFrame(data=data)
def makePatchFiles(args, verbose=0):
    """ Makes patch-level region files given a
    skyMap, star catalogue and a recipe to draw
    each mask size according to the star
    brightness

    INPUT
    -i SKYMAP,STARCAT,RADIUSFILE

    OUTPUT
    -o directory where to put the region files

    """
    """ LSST pipeline libraries
    """
    sys.stderr.write("Importing LSST pipeline libraries...")
    import lsst.daf.persistence as dafPersist
    import lsst.afw.cameraGeom as camGeom
    import lsst.afw.coord as afwCoord
    import lsst.afw.geom as afwGeom
    import lsst.afw.image as afwImage
    sys.stderr.write("Done\n")

    fileInName = args.input.split(",")
    dirOutName = args.output

    filters = ["HSC-G", "HSC-R", "HSC-I", "HSC-Z", "HSC-Y"]
    """ skyMap
    """
    sys.stderr.write("Loading sky map: {0:s}...".format(fileInName[0]))
    skyMap = pickle.load(open(fileInName[0], "rb"))
    sys.stderr.write("Done\n")

    NTracts = len(skyMap)
    """ star catalogue
    """
    sys.stderr.write("Reading star catalogue: {0:s}...".format(fileInName[1]))
    stars, _ = getCols(fileInName[1], ['source_id', 'ra', 'dec', 'G_Gaia'],
                       dictionary=True)
    Nstars = len(stars['source_id'])

    starsTree = dataTree(stars['ra'], stars['dec'])

    bright = stars['G_Gaia'] < MAG_LIMIT
    faint = stars['G_Gaia'] >= MAG_LIMIT
    sys.stderr.write("Done\n")
    """ mask radius
    """
    sys.stderr.write("Computing masks radius from: {0:s}...".format(
        fileInName[2]))
    maskRadiusPara = ascii.read(fileInName[2], header_start=-1)
    a_bright = maskRadiusPara["a"][maskRadiusPara["mask_type"] == "bright"][0]
    b_bright = maskRadiusPara["b"][maskRadiusPara["mask_type"] == "bright"][0]
    a_faint = maskRadiusPara["a"][maskRadiusPara["mask_type"] == "faint"][0]
    b_faint = maskRadiusPara["b"][maskRadiusPara["mask_type"] == "faint"][0]
    sys.stderr.write("Done\n")

    rMask = np.zeros(Nstars)
    rMask[bright] = r_vs_mag(stars['G_Gaia'][bright], a_bright,
                             b_bright)  # in arcsec
    rMask[faint] = r_vs_mag(stars['G_Gaia'][faint], a_faint,
                            b_faint)  # in arsec

    rMask /= 3600.0
    """ largest possible radius in star catalogue
    """
    starMaxRadius = max(rMask)

    sys.stderr.write("Largest mask radius: {0:f} deg\n".format(starMaxRadius))

    sys.stderr.write(
        "\r" +
        "Writing region files: {0:d}/{1:d} tracts done".format(0, NTracts))
    sys.stderr.flush()

    #sys.stderr.write("Writing region files\n".format(starMaxRadius))
    for i, tract in enumerate(skyMap):

        # if tract.getId() != 9376:
        #    continue

        wcs = tract.getWcs()
        pixelScale = wcs.pixelScale().asDegrees()
        """ maximum radii along the diagonal of the tract and patches
        """
        tractMaxRadius = max(
            tract.getBBox().getMaxX(),
            tract.getBBox().getMaxY()) * pixelScale * np.sqrt(2.) / 2.
        patchMaxRadius = (
            max(tract.getPatchInnerDimensions()) +
            tract.getPatchBorder()) * pixelScale * np.sqrt(2.) / 2.
        """ find stars around tract
        """
        raTract, decTract = tract.getCtrCoord().getRa().asDegrees(
        ), tract.getCtrCoord().getDec().asDegrees()
        starsTract = findNeighbors(starsTree, raTract, decTract,
                                   tractMaxRadius + starMaxRadius)

        Nstars = len(stars['ra'][starsTract])

        # print "\n", Nstars
        if Nstars == 0:
            if (i + 1) % 100 == 0:
                sys.stderr.write(
                    "\r" +
                    "Writing region files: {0:d}/{1:d} tracts done".format(
                        i + 1, NTracts))
                sys.stderr.flush()
            continue

        mkdir_p(dirOutName + "/patches/{0:d}".format(tract.getId()))
        mkdir_p(dirOutName + "/tracts")

        starsRa = stars['ra'][starsTract]
        starsDec = stars['dec'][starsTract]
        starsRMasks = rMask[starsTract]
        starsID = stars['source_id'][starsTract]
        starsMag = stars['G_Gaia'][starsTract]
        """ write tract file
        """
        for f in filters:
            fileOutName = dirOutName + "/tracts/" + args.basename + "-{0:d}-{1:s}.reg".format(
                tract.getId(), f)
            if f == "HSC-I":
                writeMaskFile(starsRa, starsDec,
                              starsRMasks, starsID, fileOutName, f,
                              tract.getId(), [-1, -1], starsMag)
            else:
                ln_sf(
                    args.basename +
                    "-{0:d}-{1:s}.reg".format(tract.getId(), "HSC-I"),
                    fileOutName)
        """ loop over patches
        """
        for patch in tract:
            bbox = patch.getOuterBBox()
            p = afwGeom.Point2D((bbox.getMinX() + bbox.getMaxX()) / 2.0,
                                (bbox.getMinY() + bbox.getMaxY()) / 2.0)
            center = wcs.pixelToSky(p).toIcrs()
            raPatch, decPatch = center.getRa().asDegrees(), center.getDec(
            ).asDegrees()

            D = distAngSpherDeg(raPatch, decPatch, starsRa, starsDec)

            inPatch = (D < patchMaxRadius + 1.5 * starsRMasks)

            if len(starsDec[inPatch]) == 0:
                continue

            for f in filters:
                fileOutName = dirOutName + "/patches/{0:d}/{1:s}-{0:d}-{2:d},{3:d}-{4:s}.reg".format(
                    tract.getId(), args.basename,
                    patch.getIndex()[0],
                    patch.getIndex()[1], f)
                if f == "HSC-I":
                    writeMaskFile(starsRa[inPatch], starsDec[inPatch],
                                  starsRMasks[inPatch], starsID[inPatch],
                                  fileOutName, f, tract.getId(),
                                  patch.getIndex(), starsMag[inPatch])
                else:
                    ln_sf(
                        args.basename + "-{0:d}-{1:d},{2:d}-{3:s}.reg".format(
                            tract.getId(),
                            patch.getIndex()[0],
                            patch.getIndex()[1], "HSC-I"), fileOutName)

        if (i + 1) % 100 == 0:
            sys.stderr.write("\r" +
                             "Writing region files: {0:d}/{1:d} tracts done".
                             format(i + 1, NTracts))
            sys.stderr.flush()

    sys.stderr.write("\r" +
                     "Writing region files: {0:d}/{1:d} tracts done\n".format(
                         NTracts, NTracts))
    sys.stderr.flush()

    return
Example #6
0
    def checkTanWcs(self, crval, orientation, flipX):
        """Construct a pure TAN SkyWcs and check that it operates as specified

        Parameters
        ----------
        crval : `lsst.afw.geom.SpherePoint`
            Desired reference sky position.
            Must not be at either pole.
        orientation : `lsst.afw.geom.Angle`
            Position angle of focal plane +Y, measured from N through E.
            At 0 degrees, +Y is along N and +X is along E/W if flipX false/true
            At 90 degrees, +Y is along E and +X is along S/N if flipX false/true
        flipX : `bool`
            Flip x axis? See `orientation` for details.

        Returns
        -------
        wcs : `lsst.afw.geom.SkyWcs`
            The generated pure TAN SkyWcs
        """
        cdMatrix = makeCdMatrix(scale=self.scale,
                                orientation=orientation,
                                flipX=flipX)
        wcs = makeSkyWcs(crpix=self.crpix, crval=crval, cdMatrix=cdMatrix)
        self.checkPersistence(wcs, bbox=self.bbox)
        self.checkMakeFlippedWcs(wcs)

        self.assertTrue(wcs.isFits)
        self.assertEqual(wcs.isFlipped, bool(flipX))

        xoffAng = 0 * degrees if flipX else 180 * degrees

        pixelList = [
            Point2D(self.crpix[0], self.crpix[1]),
            Point2D(self.crpix[0] + 1, self.crpix[1]),
            Point2D(self.crpix[0], self.crpix[1] + 1),
        ]
        skyList = wcs.pixelToSky(pixelList)

        # check pixels to sky
        predSkyList = [
            crval,
            crval.offset(xoffAng - orientation, self.scale),
            crval.offset(90 * degrees - orientation, self.scale),
        ]
        self.assertSpherePointListsAlmostEqual(predSkyList, skyList)
        self.assertSpherePointListsAlmostEqual(predSkyList,
                                               wcs.pixelToSky(pixelList))
        for pixel, predSky in zip(pixelList, predSkyList):
            self.assertSpherePointsAlmostEqual(predSky, wcs.pixelToSky(pixel))
            self.assertSpherePointsAlmostEqual(
                predSky, wcs.pixelToSky(pixel[0], pixel[1]))

        # check sky to pixels
        self.assertPairListsAlmostEqual(pixelList, wcs.skyToPixel(skyList))
        self.assertPairListsAlmostEqual(pixelList, wcs.skyToPixel(skyList))
        for pixel, sky in zip(pixelList, skyList):
            self.assertPairsAlmostEqual(pixel, wcs.skyToPixel(sky))
            # self.assertPairsAlmostEqual(pixel, wcs.skyToPixel(sky[0], sky[1]))

        # check CRVAL round trip
        self.assertSpherePointsAlmostEqual(wcs.getSkyOrigin(),
                                           crval,
                                           maxSep=self.tinyAngle)

        crpix = wcs.getPixelOrigin()
        self.assertPairsAlmostEqual(crpix, self.crpix, maxDiff=self.tinyPixels)

        self.assertFloatsAlmostEqual(wcs.getCdMatrix(), cdMatrix)

        pixelScale = wcs.getPixelScale()
        self.assertAnglesAlmostEqual(self.scale,
                                     pixelScale,
                                     maxDiff=self.tinyAngle)

        pixelScale = wcs.getPixelScale(self.crpix)
        self.assertAnglesAlmostEqual(self.scale,
                                     pixelScale,
                                     maxDiff=self.tinyAngle)

        # check that getFitsMetadata can operate at high precision
        # and has axis order RA, Dec
        fitsMetadata = wcs.getFitsMetadata(True)
        self.assertEqual(fitsMetadata.get("CTYPE1")[0:4], "RA--")
        self.assertEqual(fitsMetadata.get("CTYPE2")[0:4], "DEC-")

        # Compute a WCS with the pixel origin shifted by an arbitrary amount
        # The resulting sky origin should not change
        offset = Extent2D(500, -322)  # arbitrary
        shiftedWcs = wcs.copyAtShiftedPixelOrigin(offset)
        self.assertTrue(shiftedWcs.isFits)
        predShiftedPixelOrigin = self.crpix + offset
        self.assertPairsAlmostEqual(shiftedWcs.getPixelOrigin(),
                                    predShiftedPixelOrigin,
                                    maxDiff=self.tinyPixels)
        self.assertSpherePointsAlmostEqual(shiftedWcs.getSkyOrigin(),
                                           crval,
                                           maxSep=self.tinyAngle)

        shiftedPixelList = [p + offset for p in pixelList]
        shiftedSkyList = shiftedWcs.pixelToSky(shiftedPixelList)
        self.assertSpherePointListsAlmostEqual(skyList,
                                               shiftedSkyList,
                                               maxSep=self.tinyAngle)

        # Check that the shifted WCS can be round tripped as FITS metadata
        shiftedMetadata = shiftedWcs.getFitsMetadata(precise=True)
        shiftedWcsCopy = makeSkyWcs(shiftedMetadata)
        shiftedBBox = Box2D(predShiftedPixelOrigin,
                            predShiftedPixelOrigin + Extent2I(2000, 2000))
        self.assertWcsAlmostEqualOverBBox(shiftedWcs, shiftedWcsCopy,
                                          shiftedBBox)

        wcsCopy = SkyWcs.readString(wcs.writeString())
        self.assertTrue(wcsCopy.isFits)

        return wcs