def get_sky_boundary(bbox, wcs): begin_x, begin_y = bbox.beginX, bbox.beginY end_x, end_y = bbox.endX, bbox.endY sky_00 = geom.SpherePoint(wcs.pixelToSky(begin_x, begin_y)) sky_01 = geom.SpherePoint(wcs.pixelToSky(begin_x, end_y)) sky_10 = geom.SpherePoint(wcs.pixelToSky(end_x, begin_y)) sky_11 = geom.SpherePoint(wcs.pixelToSky(end_x, end_y)) ras = np.array([ sky_00.getRa().asDegrees(), sky_01.getRa().asDegrees(), sky_10.getRa().asDegrees(), sky_11.getRa().asDegrees() ]) ras.sort() decs = np.array([ sky_00.getDec().asDegrees(), sky_01.getDec().asDegrees(), sky_10.getDec().asDegrees(), sky_11.getDec().asDegrees() ]) decs.sort() radec_dict = { 'begin_ra': ras[1], 'end_ra': ras[2], 'begin_dec': decs[1], 'end_dec': decs[2] } return radec_dict
def make_afw_coords(coord_list): """ Convert list of ra and dec to lsst.afw.coord.IcrsCoord. Parameters ---------- coord_list : list of tuples or tuple ra and dec in degrees. Returns ------- afw_coords : list of lsst.afw.coord.IcrsCoord """ if type(coord_list[0]) in (float, int, np.float64): ra, dec = coord_list afw_coords = geom.SpherePoint(geom.Angle(ra, geom.degrees), geom.Angle(dec, geom.degrees)) else: afw_coords = [ geom.SpherePoint(geom.Angle(ra, geom.degrees), geom.Angle(dec, geom.degrees)) for ra, dec in coord_list ] return afw_coords
def coordFromVec(vec, defRA=None): """Convert an ICRS cartesian vector to an ICRS lsst.geom.SpherePoint Parameters ---------- vec : `list` of `float` An ICRS catesian vector. defRA : `lsst.geom.Angle` or None The RA to use if the vector is too near a pole; ignored if not near a pole. Raises ------ RuntimeError If vec too near a pole and defRA is None. """ if abs(vec[0]) < _TinyFloat and abs(vec[1]) < _TinyFloat: if defRA is None: raise RuntimeError("At pole and defRA==None") if vec[2] > 0: decDeg = 90.0 else: decDeg = -90.0 return geom.SpherePoint(defRA, decDeg * geom.degrees) return geom.SpherePoint(lsst.sphgeom.Vector3d(*vec))
def setUp(self): rawPath = os.path.join(testDataDirectory, "hsc", "raw") calibPath = os.path.join(testDataDirectory, "hsc", "calib") self.repoPath = createDataRepository("lsst.obs.hsc.HscMapper", rawPath, calibPath) self.butler = dafPersist.Butler(root=self.repoPath, calibRoot=calibPath) # The following properties of the provided data are known a priori. self.visit = 904024 self.ccdNum = 50 self.filter = 'i' self.rawSize = (2144, 4241) self.ccdSize = (2048, 4176) self.exptime = 30.0 self.darktime = self.exptime # No explicit darktime self.dateAvg = DateTime(56598.26165414352, DateTime.MJD, DateTime.TAI) self.boresightRaDec = geom.SpherePoint(320.7499250000, 0.500019444, degrees) self.boresightAzAlt = geom.SpherePoint(226.68922661, 63.04359233, degrees) self.boresightAirmass = 1.121626027604189 self.boresightRotAngle = 270.0 * degrees self.rotType = RotType.SKY self.obs_longitude = -155.476667 * degrees self.obs_latitude = 19.825556 * degrees self.obs_elevation = 4139 self.weath_airTemperature = -0.8 self.weath_airPressure = 62170. self.weath_humidity = 33.1 # NOTE: if we deal with DM-8053 and get UT1 implemented, ERA will # change slightly. self.era = 2.3659570321481826 * radians
def testFindTract(self): """Test the SkyMap.findTract method """ for numTracts in (2, 4): config = EquatSkyMap.ConfigClass() config.numTracts = numTracts skyMap = EquatSkyMap(config) decRange = skyMap.config.decRange decList = ( (decRange[0] * 0.999) + (decRange[1] * 0.901), (decRange[0] * 0.500) + (decRange[1] * 0.500), (decRange[0] * 0.091) + (decRange[1] * 0.999), ) for tractInfo0 in skyMap: tractId0 = tractInfo0.getId() ctrCoord0 = tractInfo0.getCtrCoord() for tractInfo1 in self.getNeighborTracts(skyMap, tractId0): tractId1 = tractInfo1.getId() ctrCoord1 = tractInfo1.getCtrCoord() for deltaFrac in (-0.001, 0.001): v0 = ctrCoord0.getVector() * (0.5 + deltaFrac) v1 = ctrCoord1.getVector() * (0.5 - deltaFrac) testVec = v0 + v1 testRa = geom.SpherePoint(testVec).getRa() if deltaFrac > 0.0: expectedTractId = tractId0 else: expectedTractId = tractId1 for testDecDeg in decList: testDec = geom.Angle(testDecDeg, geom.degrees) testCoord = geom.SpherePoint(testRa, testDec) nearestTractInfo = skyMap.findTract(testCoord) nearestTractId = nearestTractInfo.getId() self.assertEqual(nearestTractId, expectedTractId) patchInfo = nearestTractInfo.findPatch(testCoord) pixelInd = geom.Point2I(nearestTractInfo.getWcs().skyToPixel(testCoord)) self.assertTrue(patchInfo.getInnerBBox().contains(pixelInd)) # find a point outside the tract and make sure it fails tractInfo = tractInfo0 wcs = tractInfo.getWcs() bbox = geom.Box2D(tractInfo.getBBox()) outerPixPosList = [ bbox.getMin() - geom.Extent2D(1, 1), geom.Point2D(bbox.getMaxX(), bbox.getMinY()) - geom.Extent2D(1, 1), bbox.getMax() + geom.Extent2D(1, 1), geom.Point2D(bbox.getMinX(), bbox.getMaxY()) + geom.Extent2D(1, 1), ] for outerPixPos in outerPixPosList: testCoord = wcs.pixelToSky(outerPixPos) self.assertRaises(LookupError, tractInfo.findPatch, testCoord)
def calculateAstropyDcr(visitInfo, wcs, filterInfo, dcrNumSubfilters): """Calculate the DCR shift using astropy coordinate transformations. Parameters ---------- visitInfo : `lsst.afw.image.VisitInfo` VisitInfo for the exposure. wcs : `lsst.afw.geom.skyWcs.SkyWcs` A wcs that matches the inputs. filterInfo : `lsst.afw.image.Filter` The filter definition, set in the current instruments' obs package. dcrNumSubfilters : `int` Number of sub-filters used to model chromatic effects within a band. Returns ------- dcrShift : `tuple` of two `float` The 2D shift due to DCR, in pixels. Uses numpy axes ordering (Y, X). """ elevation = visitInfo.getBoresightAzAlt().getLatitude() azimuth = visitInfo.getBoresightAzAlt().getLongitude() lambdaEff = filterInfo.getFilterProperty().getLambdaEff() loc = EarthLocation(lat=visitInfo.getObservatory().getLatitude().asDegrees()*u.degree, lon=visitInfo.getObservatory().getLongitude().asDegrees()*u.degree, height=visitInfo.getObservatory().getElevation()*u.m) date = visitInfo.getDate() time = Time(date.get(date.MJD, date.TAI), format='mjd', location=loc, scale='tai') altaz = SkyCoord(alt=elevation.asDegrees(), az=azimuth.asDegrees(), unit='deg', obstime=time, frame='altaz', location=loc) # The DCR calculations are performed at the boresight ra0 = altaz.icrs.ra.degree*degrees dec0 = altaz.icrs.dec.degree*degrees x0, y0 = wcs.skyToPixel(geom.SpherePoint(ra0, dec0)) dcrShift = [] # We divide the filter into "subfilters" with the full wavelength range # divided into equal sub-ranges. for wl0, wl1 in wavelengthGenerator(filterInfo, dcrNumSubfilters): # Note that diffRefractAmp can be negative, # since it is relative to the midpoint of the full band diffRefractAmp0 = differentialRefraction(wavelength=wl0, wavelengthRef=lambdaEff, elevation=elevation, observatory=visitInfo.getObservatory(), weather=visitInfo.getWeather()) diffRefractAmp1 = differentialRefraction(wavelength=wl1, wavelengthRef=lambdaEff, elevation=elevation, observatory=visitInfo.getObservatory(), weather=visitInfo.getWeather()) diffRefractAmp = (diffRefractAmp0 + diffRefractAmp1)/2. elevation1 = elevation + diffRefractAmp altaz = SkyCoord(alt=elevation1.asDegrees(), az=azimuth.asDegrees(), unit='deg', obstime=time, frame='altaz', location=loc) ra1 = altaz.icrs.ra.degree*degrees dec1 = altaz.icrs.dec.degree*degrees x1, y1 = wcs.skyToPixel(geom.SpherePoint(ra1, dec1)) dcrShift.append((y1-y0, x1-x0)) return dcrShift
def testRun(self): """Test the run method. """ fakesConfig = CreateRandomApFakesConfig() fakesConfig.fraction = 0.5 fakesConfig.fakeDensity = self.sourceDensity fakesTask = CreateRandomApFakesTask(config=fakesConfig) bCircle = self.simpleMap.generateTract(self.tractId).getInnerSkyPolygon().getBoundingCircle() result = fakesTask.run(self.tractId, self.simpleMap) fakeCat = result.fakeCat self.assertEqual(len(fakeCat), self.nSources) for idx, row in fakeCat.iterrows(): self.assertTrue( bCircle.contains( geom.SpherePoint(row[fakesTask.config.raColName], row[fakesTask.config.decColName], geom.radians).getVector())) self.assertEqual(fakeCat[fakesConfig.visitSourceFlagCol].sum(), self.nInVisit) self.assertEqual(fakeCat[fakesConfig.templateSourceFlagCol].sum(), self.nInTemplate) for f in fakesConfig.filterSet: filterMags = fakeCat[fakesConfig.magVar % f] self.assertEqual(self.nSources, len(filterMags)) self.assertTrue( np.all(fakesConfig.magMin <= filterMags)) self.assertTrue( np.all(fakesConfig.magMax > filterMags))
def generateTract(self, index): """Generate TractInfo for the specified tract index.""" center = geom.SpherePoint(self.config.raList[index], self.config.decList[index], geom.degrees) radius = self.config.radiusList[index] wcs = self._wcsFactory.makeWcs(crPixPos=geom.Point2D(0, 0), crValCoord=center) return ExplicitTractInfo(index, self.config.patchInnerDimensions, self.config.patchBorder, center, radius*geom.degrees, self.config.tractOverlap*geom.degrees, wcs)
def make_stamps(n_stamps=3): stampSize = 25 # create dummy stamp stamps stampImages = [ afwImage.maskedImage.MaskedImageF(stampSize, stampSize) for _ in range(n_stamps) ] for stampIm in stampImages: stampImArray = stampIm.image.array stampImArray += np.random.rand(stampSize, stampSize) stampMaskArray = stampIm.mask.array stampMaskArray += 10 stampVarArray = stampIm.variance.array stampVarArray += 1000. ras = np.random.rand(n_stamps) * 360. decs = np.random.rand(n_stamps) * 180 - 90 stamp_list = [ stamps.Stamp(stamp_im=stampIm, position=geom.SpherePoint(geom.Angle(ra, geom.degrees), geom.Angle(dec, geom.degrees))) for stampIm, ra, dec in zip(stampImages, ras, decs) ] metadata = PropertyList() metadata['RA_DEG'] = ras metadata['DEC_DEG'] = decs return stamps.Stamps(stamp_list, metadata=metadata)
def averageRaDec(ra, dec): """Calculate average RA, Dec from input lists using spherical geometry. Parameters ---------- ra : `list` [`float`] RA in [radians] dec : `list` [`float`] Dec in [radians] Returns ------- float, float meanRa, meanDec -- Tuple of average RA, Dec [radians] """ assert (len(ra) == len(dec)) angleRa = [geom.Angle(r, geom.radians) for r in ra] angleDec = [geom.Angle(d, geom.radians) for d in dec] coords = [ geom.SpherePoint(ar, ad, geom.radians) for (ar, ad) in zip(angleRa, angleDec) ] meanRa, meanDec = geom.averageSpherePoint(coords) return meanRa.asRadians(), meanDec.asRadians()
def _convert_from_pandas(self, input_objects): """Create minimal schema SourceCatalog from a pandas DataFrame. We need a catalog of this type to run within the forced measurement subtask. Parameters ---------- input_objects : `pandas.DataFrame` DiaObjects with locations and ids. `` Returns ------- outputCatalog : `lsst.afw.table.SourceTable` Output catalog with minimal schema. """ schema = afwTable.SourceTable.makeMinimalSchema() outputCatalog = afwTable.SourceCatalog(schema) outputCatalog.reserve(len(input_objects)) for obj_id, df_row in input_objects.iterrows(): outputRecord = outputCatalog.addNew() outputRecord.setId(obj_id) outputRecord.setCoord( geom.SpherePoint(df_row["ra"], df_row["decl"], geom.degrees)) return outputCatalog
def make_stamps(n_stamps=3, use_archive=False): stampSize = 25 # create dummy stamp stamps stampImages = [ afwImage.maskedImage.MaskedImageF(stampSize, stampSize) for _ in range(n_stamps) ] for stampIm in stampImages: stampImArray = stampIm.image.array stampImArray += np.random.rand(stampSize, stampSize) stampMaskArray = stampIm.mask.array stampMaskArray += 10 stampVarArray = stampIm.variance.array stampVarArray += 1000. ras = np.random.rand(n_stamps) * 360. decs = np.random.rand(n_stamps) * 180 - 90 archive_elements = [ tF.makeTransform(geom.AffineTransform(np.random.rand(2))) if use_archive else None for _ in range(n_stamps) ] stamp_list = [ stamps.Stamp(stamp_im=stampIm, position=geom.SpherePoint(geom.Angle(ra, geom.degrees), geom.Angle(dec, geom.degrees)), archive_element=ae) for stampIm, ra, dec, ae in zip( stampImages, ras, decs, archive_elements) ] metadata = PropertyList() metadata['RA_DEG'] = ras metadata['DEC_DEG'] = decs return stamps.Stamps(stamp_list, metadata=metadata, use_archive=True)
def test_coadd_transmission_curves(self): """Test that coadded TransmissionCurves agree with the inputs.""" wavelengths = np.linspace(4000, 7000, 10) n_object_test = 10 ctx = np.random.RandomState(12345) for band in self._bands: n_tested = 0 exp = self.butler.get("deepCoadd_calexp", band=band, tract=self._tract, patch=self._patch) cat = self.butler.get("objectTable", band=band, tract=self._tract, patch=self._patch) transmission_curve = exp.getInfo().getTransmissionCurve() coadd_inputs = exp.getInfo().getCoaddInputs().ccds wcs = exp.getWcs() to_check = ctx.choice(len(cat), size=n_object_test, replace=False) for index in to_check: coadd_coord = geom.SpherePoint(cat["coord_ra"].values[index]*geom.degrees, cat["coord_dec"].values[index]*geom.degrees) summed_throughput = np.zeros(wavelengths.shape, dtype=np.float64) weight_sum = 0.0 for rec in coadd_inputs.subsetContaining(coadd_coord, includeValidPolygon=True): det_pos = rec.getWcs().skyToPixel(coadd_coord) det_trans = rec.getTransmissionCurve() weight = rec.get("weight") summed_throughput += det_trans.sampleAt(det_pos, wavelengths)*weight weight_sum += weight if weight_sum == 0.0: continue summed_throughput /= weight_sum coadd_pos = wcs.skyToPixel(coadd_coord) coadd_throughput = transmission_curve.sampleAt(coadd_pos, wavelengths) np.testing.assert_array_almost_equal(coadd_throughput, summed_throughput) n_tested += 1 self.assertGreater(n_tested, 5)
def computeReferencePixelScale(camera): """ Compute the median pixel scale in the camera Returns ------- pixelScale: `float` Average pixel scale (arcsecond) over the camera """ boresight = geom.SpherePoint(180.0*geom.degrees, 0.0*geom.degrees) orientation = 0.0*geom.degrees flipX = False # Create a temporary visitInfo for input to createInitialSkyWcs visitInfo = afwImage.VisitInfo(boresightRaDec=boresight, boresightRotAngle=orientation, rotType=afwImage.visitInfo.RotType.SKY) pixelScales = np.zeros(len(camera)) for i, detector in enumerate(camera): wcs = createInitialSkyWcs(visitInfo, detector, flipX) pixelScales[i] = wcs.getPixelScale().asArcseconds() ok, = np.where(pixelScales > 0.0) return np.median(pixelScales[ok])
def _trimToPatch(self, cat, innerPatchBox, wcs): """Create generator testing if a set of DiaSources are in the patch/tract. Parameters ---------- cat : `pandas.DataFrame` Catalog of DiaSources to test within patch/tract. innerPatchBox : `lsst.geom.Box2D` Bounding box of the patch. wcs : `lsst.geom.SkyWcs` Wcs of the tract. Returns ------ isInPatch : `numpy.ndarray`, (N,) Booleans representing if the DiaSources are contained within the current patch and tract. """ isInPatch = np.array([ innerPatchBox.contains( wcs.skyToPixel( geom.SpherePoint(row["ra"], row["decl"], geom.degrees))) for idx, row in cat.iterrows()]) return isInPatch
def makeDummyWcs(self, rotAngle=None, pixelScale=None, crval=None, flipX=True): """Make a World Coordinate System object for testing. Parameters ---------- rotAngle : `lsst.geom.Angle` Rotation of the CD matrix, East from North pixelScale : `lsst.geom.Angle` Pixel scale of the projection. crval : `lsst.afw.geom.SpherePoint` Coordinates of the reference pixel of the wcs. flipX : `bool`, optional Flip the direction of increasing Right Ascension. Returns ------- wcs : `lsst.afw.geom.skyWcs.SkyWcs` A wcs that matches the inputs. """ if rotAngle is None: rotAngle = self.rotAngle if pixelScale is None: pixelScale = self.pixelScale if crval is None: crval = geom.SpherePoint(self.ra, self.dec) crpix = geom.Box2D(self.bbox).getCenter() cdMatrix = afwGeom.makeCdMatrix(scale=pixelScale, orientation=rotAngle, flipX=flipX) wcs = afwGeom.makeSkyWcs(crpix=crpix, crval=crval, cdMatrix=cdMatrix) return wcs
def makeMatches(self, refCat, srcCat, nSrc): for i in range(nSrc): refSrc = refCat.addNew() srcSrc = srcCat.addNew() raDeg, decDeg = np.random.randn(2) coord = geom.SpherePoint(raDeg, decDeg, geom.degrees) refSrc.set("g_flux", 10**(-0.4 * 18)) refSrc.set("r_flux", 10**(-0.4 * 18)) refSrc.set("resolved", False) refSrc.set("photometric", True) refSrc.setCoord(coord) srcSrc.setCoord(coord) srcSrc.set("slot_PsfFlux_instFlux", 10.) srcSrc.set("slot_PsfFlux_instFluxErr", 1.) for flag in self.sourceSelector.config.badFlags: srcSrc.set(flag, False) mc = afwTable.MatchControl() mc.symmetricMatch = False mat = afwTable.matchRaDec(refCat, srcCat, 1.0 * geom.arcseconds, mc) self.assertEqual(len(mat), nSrc) return mat
def _transformAndCheck(self, measConf, schema, transformTask): """Check the results of applying transformTask to a SourceCatalog. @param[in] measConf Measurement plugin configuration. @param[in] schema Input catalog schema. @param[in] transformTask Instance of TransformTask to be applied. For internal use by this test case. """ # There should now be one transformation registered per measurement plugin. self.assertEqual(len(measConf.plugins.names), len(transformTask.transforms)) # Rather than do a real measurement, we use a dummy source catalog # containing a source at an arbitrary position. inCat = afwTable.SourceCatalog(schema) r = inCat.addNew() r.setCoord(geom.SpherePoint(0.0, 11.19, geom.degrees)) r[PLUGIN_NAME] = 1.0 wcs, photoCalib = Placeholder(), Placeholder() outCat = transformTask.run(inCat, wcs, photoCalib) # Check that all sources have been transformed appropriately. for inSrc, outSrc in zip(inCat, outCat): self.assertEqual(outSrc[PLUGIN_NAME], inSrc[PLUGIN_NAME]) self.assertEqual(outSrc[PLUGIN_NAME + "_transform"], inSrc[PLUGIN_NAME] * -1.0) for field in transformTask.config.toDict()['copyFields']: self.assertEqual(outSrc.get(field), inSrc.get(field)) # Check that the wcs and photoCalib objects were accessed once per transform. self.assertEqual(wcs.count, len(transformTask.transforms)) self.assertEqual(photoCalib.count, len(transformTask.transforms))
def testMakeAlertDict(self): """Test stripping data from the various data products and into a dictionary "alert". """ packageAlerts = PackageAlertsTask() alertId = 1234 for srcIdx, diaSource in self.diaSources.iterrows(): sphPoint = geom.SpherePoint(diaSource["ra"], diaSource["decl"], geom.degrees) cutout = self.exposure.getCutout( sphPoint, geom.Extent2I(self.cutoutSize, self.cutoutSize)) ccdCutout = packageAlerts.createCcdDataCutout( cutout, sphPoint, geom.Extent2I(self.cutoutSize, self.cutoutSize), cutout.getPhotoCalib(), 1234) cutoutBytes = packageAlerts.streamCcdDataToBytes(ccdCutout) objSources = self.diaSourceHistory.loc[srcIdx[0]] objForcedSources = self.diaForcedSources.loc[srcIdx[0]] alert = packageAlerts.makeAlertDict(alertId, diaSource, self.diaObjects.loc[srcIdx[0]], objSources, objForcedSources, ccdCutout, ccdCutout) self.assertEqual(len(alert), 9) self.assertEqual(alert["alertId"], alertId) self.assertEqual(alert["diaSource"], diaSource.to_dict()) self.assertEqual(alert["cutoutDifference"], cutoutBytes) self.assertEqual(alert["cutoutTemplate"], cutoutBytes)
def __init__(self, camera, defaultOrientation): self.camera = camera # Put the reference boresight at the equator to avoid cos(dec) problems. self.boresight = geom.SpherePoint(180.0 * geom.degrees, 0.0 * geom.degrees) self.flipX = False self.defaultOrientation = int(defaultOrientation) % 360
def create_test_points_pandas(point_locs_deg, wcs=None, start_id=0, schema=None, scatter_arcsec=1.0, indexer_ids=None, associated_ids=None): """Create dummy DIASources or DIAObjects for use in our tests. Parameters ---------- point_locs_deg : array-like (N, 2) of `float`s Positions of the test points to create in RA, DEC. wcs : `lsst.afw.geom.SkyWcs` Wcs to convert RA/Dec to x/y if provided. start_id : `int` Unique id of the first object to create. The remaining sources are incremented by one from the first id. schema : `lsst.afw.table.Schema` Schema of the objects to create. Defaults to the DIASource schema. scatter_arcsec : `float` Scatter to add to the position of each DIASource. indexer_ids : `list` of `ints`s Id numbers of pixelization indexer to store. Must be the same length as the first dimension of point_locs_deg. associated_ids : `list` of `ints`s Id numbers of associated DIAObjects to store. Must be the same length as the first dimension of point_locs_deg. Returns ------- test_points : `pandas.DataFrame` Catalog of points to test. """ if schema is None: schema = make_dia_source_schema() sources = afwTable.SourceCatalog(schema) for src_idx, (ra, dec,) in enumerate(point_locs_deg): src = sources.addNew() src['id'] = src_idx + start_id coord = geom.SpherePoint(ra, dec, geom.degrees) if scatter_arcsec > 0.0: coord = coord.offset( np.random.rand() * 360 * geom.degrees, np.random.rand() * scatter_arcsec * geom.arcseconds) if indexer_ids is not None: src['pixelId'] = indexer_ids[src_idx] if associated_ids is not None: src['diaObjectId'] = associated_ids[src_idx] src.setCoord(coord) if wcs is not None: xyCentroid = wcs.skykToPixel(coord) src.set("x", xyCentroid.getX()) src.set("y", xyCentroid.getY()) sources = sources.asAstropy().to_pandas() return sources
def in_image(ra, dec, wcs, bbox, offset): radec = geom.SpherePoint(ra, dec, geom.degrees) xy = wcs.skyToPixel(radec) phy_x, phy_y = xy.getX(), xy.getY() if bbox.beginX + offset <= phy_x and bbox.endX - offset >= phy_x and \ bbox.beginY + offset <= phy_y and bbox.endY - offset >= phy_y: return True else: return False
def testTractContains(self): """Test that TractInfo.contains works""" skyMap = self.getSkyMap() for tract in skyMap: coord = tract.getCtrCoord() self.assertTrue(tract.contains(coord)) opposite = geom.SpherePoint(coord.getLongitude() + 12 * geom.hours, -1 * coord.getLatitude()) self.assertFalse(tract.contains(opposite))
def angToCoord(thetaphi): """Convert healpy's ang to an lsst.geom.SpherePoint The ang is provided as a single object, thetaphi, so the output of healpy functions can be directed to this function without additional translation. """ return geom.SpherePoint(float(thetaphi[1]), float(thetaphi[0] - 0.5 * numpy.pi), geom.radians)
def makeitLsst(prefs, context, saveWcs=False, plot=dict()): """This is the python wrapper that reads lsst tables """ # Create an array of PSFs (one PSF for each extension) if prefs.getVerboseType() != prefs.QUIET: print("----- %d input catalogues:" % prefs.getNcat()) if saveWcs: # only needed for making plots wcssList = [] fields = psfexLib.vectorField() for cat in prefs.getCatalogs(): field = psfexLib.Field(cat) wcss = [] wcssList.append(wcss) with fits.open(cat): # Hack: I want the WCS so I'll guess where the calexp is to be # found calexpFile = guessCalexp(cat) md = readMetadata(calexpFile) wcs = afwGeom.makeSkyWcs(md) if not wcs: cdMatrix = np.array([1.0, 0.0, 0.0, 1.0]) cdMatrix.shape = (2, 2) wcs = afwGeom.makeSkyWcs(crpix=geom.PointD(0, 0), crval=geom.SpherePoint( 0.0, 0.0, geom.degrees), cdMatrix=cdMatrix) naxis1, naxis2 = md.getScalar("NAXIS1"), md.getScalar("NAXIS2") # Find how many rows there are in the catalogue md = readMetadata(cat) field.addExt(wcs, naxis1, naxis2, md.getScalar("NAXIS2")) if saveWcs: wcss.append((wcs, naxis1, naxis2)) field.finalize() fields.append(field) fields[0].getNext() # number of extensions prefs.getPsfStep() sets = psfexLib.vectorSet() for set in load_samplesLsst(prefs, context, plot=plot): sets.append(set) psfexLib.makeit(fields, sets) ret = [[f.getPsfs() for f in fields], sets] if saveWcs: ret.append(wcssList) return ret
def validate(xs, ys, mapper, wcs): dists = [] for i in range(len(xs)): tuple1 = mapper.xyToRaDec(xs[i], ys[i]) coord1 = geom.SpherePoint(tuple1[0], tuple1[1], geom.radians) coord2 = wcs.pixelToSky(xs[i], ys[i]) dist = coord1.separation(coord2).asArcseconds() dists.append(dist) print(np.mean(dists), np.std(dists))
def makeVisitInfo(): """Return a non-NaN visitInfo.""" return afwImage.VisitInfo( exposureId=10313423, exposureTime=10.01, darkTime=11.02, date=dafBase.DateTime(65321.1, dafBase.DateTime.MJD, dafBase.DateTime.TAI), ut1=12345.1, era=45.1 * geom.degrees, boresightRaDec=geom.SpherePoint(23.1, 73.2, geom.degrees), boresightAzAlt=geom.SpherePoint(134.5, 33.3, geom.degrees), boresightAirmass=1.73, boresightRotAngle=73.2 * geom.degrees, rotType=afwImage.RotType.SKY, observatory=Observatory(11.1 * geom.degrees, 22.2 * geom.degrees, 0.333), weather=Weather(1.1, 2.2, 34.5), )
def runMeasurement(self, algorithmName, imageid, x, y, v): """Run the measurement algorithm on an image""" # load the test image imgFile = os.path.join(self.dataDir, "image.%d.fits" % imageid) img = afwImage.ImageF(imgFile) img -= self.bkgd nx, ny = img.getWidth(), img.getHeight() msk = afwImage.Mask(geom.Extent2I(nx, ny), 0x0) var = afwImage.ImageF(geom.Extent2I(nx, ny), v) mimg = afwImage.MaskedImageF(img, msk, var) msk.getArray()[:] = np.where(np.fabs(img.getArray()) < 1.0e-8, msk.getPlaneBitMask("BAD"), 0) # Put it in a bigger image, in case it matters big = afwImage.MaskedImageF(self.offset + mimg.getDimensions()) big.getImage().set(0) big.getMask().set(0) big.getVariance().set(v) subBig = afwImage.MaskedImageF(big, geom.Box2I(big.getXY0() + self.offset, mimg.getDimensions())) subBig <<= mimg mimg = big mimg.setXY0(self.xy0) exposure = afwImage.makeExposure(mimg) cdMatrix = np.array([1.0/(2.53*3600.0), 0.0, 0.0, 1.0/(2.53*3600.0)]) cdMatrix.shape = (2, 2) exposure.setWcs(afwGeom.makeSkyWcs(crpix=geom.Point2D(1.0, 1.0), crval=geom.SpherePoint(0, 0, geom.degrees), cdMatrix=cdMatrix)) # load the corresponding test psf psfFile = os.path.join(self.dataDir, "psf.%d.fits" % imageid) psfImg = afwImage.ImageD(psfFile) psfImg -= self.bkgd kernel = afwMath.FixedKernel(psfImg) kernelPsf = algorithms.KernelPsf(kernel) exposure.setPsf(kernelPsf) # perform the shape measurement msConfig = base.SingleFrameMeasurementConfig() alg = base.SingleFramePlugin.registry[algorithmName].PluginClass.AlgClass control = base.SingleFramePlugin.registry[algorithmName].PluginClass.ConfigClass().makeControl() msConfig.algorithms.names = [algorithmName] # Note: It is essential to remove the floating point part of the position for the # Algorithm._apply. Otherwise, when the PSF is realised it will have been warped # to account for the sub-pixel offset and we won't get *exactly* this PSF. plugin, table = makePluginAndCat(alg, algorithmName, control, centroid="centroid") center = geom.Point2D(int(x), int(y)) + geom.Extent2D(self.offset + geom.Extent2I(self.xy0)) source = table.makeRecord() source.set("centroid_x", center.getX()) source.set("centroid_y", center.getY()) source.setFootprint(afwDetection.Footprint(afwGeom.SpanSet(exposure.getBBox(afwImage.PARENT)))) plugin.measure(source, exposure) return source
def vizierLocationForTarget(exp, target, doMotionCorrection): """Get the target location from Vizier optionally correction motion. Parameters ---------- target : `str` The name of the target, e.g. 'HD 55852' Returns ------- targetLocation : `lsst.geom.SpherePoint` or `None` Location of the target object, optionally corrected for proper motion and parallax. Raises ------ ValueError If object not found in Hipparcos2 via Vizier. This is quite common, even for bright objects. """ # do not import at the module level - tests crash due to a race # condition with directory creation from astroquery.vizier import Vizier result = Vizier.query_object( target) # result is an empty table list for an unknown target try: star = result['I/311/hip2'] except TypeError: # if 'I/311/hip2' not in result (result doesn't allow easy checking without a try) raise ValueError epoch = "J1991.25" coord = SkyCoord( ra=star[0]['RArad'] * u.Unit(star['RArad'].unit), dec=star[0]['DErad'] * u.Unit(star['DErad'].unit), obstime=epoch, pm_ra_cosdec=star[0]['pmRA'] * u.Unit(star['pmRA'].unit), # NB contains cosdec already pm_dec=star[0]['pmDE'] * u.Unit(star['pmDE'].unit), distance=Distance(parallax=star[0]['Plx'] * u.Unit(star['Plx'].unit))) if doMotionCorrection: expDate = exp.getInfo().getVisitInfo().getDate() obsTime = astropy.time.Time(expDate.get(expDate.EPOCH), format='jyear', scale='tai') newCoord = coord.apply_space_motion(new_obstime=obsTime) else: newCoord = coord raRad, decRad = newCoord.ra.rad, newCoord.dec.rad ra = geom.Angle(raRad) dec = geom.Angle(decRad) targetLocation = geom.SpherePoint(ra, dec) return targetLocation
def make_cutout(exposure, x, y, cutout_size=60): """Make a cutout exposure at (x, y) pixel coordinate. exposure: lsst.afw.image.exposure.exposure.ExposureF x: x pixel coordinate y: y pixel coordinate cutout_size: Width(in pixel unit) of the postage stamp , default value is 60 """ cutout_extent = geom.ExtentI(cutout_size, cutout_size) radec = geom.SpherePoint(exposure.getWcs().pixelToSky(x, y)) cutout_image = exposure.getCutout(radec, cutout_extent) return cutout_image