886def applyProperMotionsImpl(log, catalog, epoch):
887 """Apply proper motion correction to a reference catalog.
888
889 Adjust position and position error in the ``catalog``
890 for proper motion to the specified ``epoch``,
891 modifying the catalog in place.
892
893 Parameters
894 ----------
895 log : `lsst.log.Log` or `logging.Logger`
896 Log object to write to.
897 catalog : `lsst.afw.table.SimpleCatalog`
898 Catalog of positions, containing:
899
900 - Coordinates, retrieved by the table's coordinate key.
901 - ``coord_raErr`` : Error in Right Ascension (rad).
902 - ``coord_decErr`` : Error in Declination (rad).
903 - ``pm_ra`` : Proper motion in Right Ascension (rad/yr,
904 East positive)
905 - ``pm_raErr`` : Error in ``pm_ra`` (rad/yr), optional.
906 - ``pm_dec`` : Proper motion in Declination (rad/yr,
907 North positive)
908 - ``pm_decErr`` : Error in ``pm_dec`` (rad/yr), optional.
909 - ``epoch`` : Mean epoch of object (an astropy.time.Time)
910 epoch : `astropy.time.Time`
911 Epoch to which to correct proper motion.
912 """
913 if "epoch" not in catalog.schema or "pm_ra" not in catalog.schema or "pm_dec" not in catalog.schema:
914 log.warning("Proper motion correction not available from catalog")
915 return
916 if not catalog.isContiguous():
917 raise RuntimeError("Catalog must be contiguous")
918 catEpoch = astropy.time.Time(catalog["epoch"], scale="tai", format="mjd")
919 log.info("Correcting reference catalog for proper motion to %r", epoch)
920
921 timeDiffsYears = (epoch.tai - catEpoch).to(astropy.units.yr).value
922 coordKey = catalog.table.getCoordKey()
923
924
925 pmRaRad = catalog["pm_ra"]
926 pmDecRad = catalog["pm_dec"]
927 offsetsRaRad = pmRaRad*timeDiffsYears
928 offsetsDecRad = pmDecRad*timeDiffsYears
929
930
931
932
933
934
935
936 offsetBearingsRad = numpy.arctan2(offsetsDecRad*1e6, offsetsRaRad*1e6)
937 offsetAmountsRad = numpy.hypot(offsetsRaRad, offsetsDecRad)
938 for record, bearingRad, amountRad in zip(catalog, offsetBearingsRad, offsetAmountsRad):
939 record.set(coordKey,
940 record.get(coordKey).offset(bearing=bearingRad*geom.radians,
941 amount=amountRad*geom.radians))
942
943
944 if "coord_raErr" in catalog.schema:
945 catalog["coord_raErr"] = numpy.hypot(catalog["coord_raErr"],
946 catalog["pm_raErr"]*timeDiffsYears)
947 if "coord_decErr" in catalog.schema:
948 catalog["coord_decErr"] = numpy.hypot(catalog["coord_decErr"],
949 catalog["pm_decErr"]*timeDiffsYears)