def test_sphDist(self):
     """Test great circle angular separation calculation."""
     expected = np.fabs(np.radians(np.linspace(-10., 10., 101)))
     cat = self.makeDataHorizontal()
     ra_mean, dec_mean = (0., 0.)
     result = sphDist(ra_mean, dec_mean, cat['coord_ra'], cat['coord_dec'])
     self.assertTrue(np.allclose(result, expected, atol=1.e-15))
Beispiel #2
0
def matchVisitComputeDistance(visit_obj1, ra_obj1, dec_obj1,
                              visit_obj2, ra_obj2, dec_obj2):
    """Calculate obj1-obj2 distance for each visit in which both objects are seen.
    For each visit shared between visit_obj1 and visit_obj2,
    calculate the spherical distance between the obj1 and obj2.
    visit_obj1 and visit_obj2 are assumed to be unsorted.
    Parameters
    ----------
    visit_obj1 : scalar, list, or numpy.array of int or str
        List of visits for object 1.
    ra_obj1 : scalar, list, or numpy.array of float
        List of RA in each visit for object 1.  [radians]
    dec_obj1 : scalar, list or numpy.array of float
        List of Dec in each visit for object 1. [radians]
    visit_obj2 : list or numpy.array of int or str
        List of visits for object 2.
    ra_obj2 : list or numpy.array of float
        List of RA in each visit for object 2.  [radians]
    dec_obj2 : list or numpy.array of float
        List of Dec in each visit for object 2.  [radians]
    Results
    -------
    list of float
        spherical distances (in radians) for matching visits.
    """
    distances = []
    visit_obj1_idx = np.argsort(visit_obj1)
    visit_obj2_idx = np.argsort(visit_obj2)
    j_raw = 0
    j = visit_obj2_idx[j_raw]
    for i in visit_obj1_idx:
        while (visit_obj2[j] < visit_obj1[i]) and (j_raw < len(visit_obj2_idx)-1):
            j_raw += 1
            j = visit_obj2_idx[j_raw]
        if visit_obj2[j] == visit_obj1[i]:
            if np.isfinite([ra_obj1[i], dec_obj1[i],
                            ra_obj2[j], dec_obj2[j]]).all():
                distances.append(sphDist(ra_obj1[i], dec_obj1[i],
                                         ra_obj2[j], dec_obj2[j]))
    return distances
Beispiel #3
0
def calcRmsDistances(groupView, annulus, magRange, verbose=False):
    """Calculate the RMS distance of a set of matched objects over visits.
    Parameters
    ----------
    groupView : lsst.afw.table.GroupView
        GroupView object of matched observations from MultiMatch.
    annulus : length-2 `astropy.units.Quantity`
        Distance range (i.e., arcmin) in which to compare objects.
        E.g., `annulus=np.array([19, 21]) * u.arcmin` would consider all
        objects separated from each other between 19 and 21 arcminutes.
    magRange : length-2 `astropy.units.Quantity`
        Magnitude range from which to select objects.
    verbose : bool, optional
        Output additional information on the analysis steps.
    Returns
    -------
    rmsDistances : `astropy.units.Quantity`
        RMS angular separations of a set of matched objects over visits.
    """

    # First we make a list of the keys that we want the fields for
    importantKeys = [groupView.schema.find(name).key for
                     name in ['id', 'coord_ra', 'coord_dec',
                              'object', 'visit', 'base_PsfFlux_mag']]

    minMag, maxMag = magRange.to(u.mag).value

    def magInRange(cat):
        mag = cat.get('base_PsfFlux_mag')
        w, = np.where(np.isfinite(mag))
        medianMag = np.median(mag[w])
        return minMag <= medianMag and medianMag < maxMag

    groupViewInMagRange = groupView.where(magInRange)

    # List of lists of id, importantValue
    matchKeyOutput = [obj.get(key)
                      for key in importantKeys
                      for obj in groupViewInMagRange.groups]

    jump = len(groupViewInMagRange)

    ra = matchKeyOutput[1*jump:2*jump]
    dec = matchKeyOutput[2*jump:3*jump]
    visit = matchKeyOutput[4*jump:5*jump]

    # Calculate the mean position of each object from its constituent visits
    # `aggregate` calulates a quantity for each object in the groupView.
    meanRa = groupViewInMagRange.aggregate(averageRaFromCat)
    meanDec = groupViewInMagRange.aggregate(averageDecFromCat)

    annulusRadians = arcminToRadians(annulus.to(u.arcmin).value)

    rmsDistances = list()
    for obj1, (ra1, dec1, visit1) in enumerate(zip(meanRa, meanDec, visit)):
        dist = sphDist(ra1, dec1, meanRa[obj1+1:], meanDec[obj1+1:])
        objectsInAnnulus, = np.where((annulusRadians[0] <= dist)
                                     & (dist < annulusRadians[1]))
        for obj2 in objectsInAnnulus:
            distances = matchVisitComputeDistance(
                visit[obj1], ra[obj1], dec[obj1],
                visit[obj2], ra[obj2], dec[obj2])
            if not distances:
                if verbose:
                    print("No matching visits found for objs: %d and %d" %
                          (obj1, obj2))
                continue

            finiteEntries, = np.where(np.isfinite(distances))
            # Need at least 2 distances to get a finite sample stdev
            if len(finiteEntries) > 1:
                # ddof=1 to get sample standard deviation (e.g., 1/(n-1))
                rmsDist = np.std(np.array(distances)[finiteEntries], ddof=1)
                rmsDistances.append(rmsDist)

    # return quantity
    rmsDistances = np.array(rmsDistances) * u.radian
    return rmsDistances
Beispiel #4
0
def calcRmsDistancesVsRef(groupView, refVisit, magRange, band, verbose=False):
    """Calculate the RMS distance of a set of matched objects over visits.
    Parameters
    ----------
    groupView : lsst.afw.table.GroupView
        GroupView object of matched observations from MultiMatch.
    magRange : length-2 `astropy.units.Quantity`
        Magnitude range from which to select objects.
    verbose : bool, optional
        Output additional information on the analysis steps.
    Returns
    -------
    rmsDistances : `astropy.units.Quantity`
        RMS angular separations of a set of matched objects over visits.
    separations : `astropy.units.Quantity`
        Angular separations of the set a matched objects.
    """

    minMag, maxMag = magRange.to(u.mag).value

    def magInRange(cat):
        mag = cat.get('base_PsfFlux_mag')
        w, = np.where(np.isfinite(mag))
        medianMag = np.median(mag[w])
        return minMag <= medianMag and medianMag < maxMag

    groupViewInMagRange = groupView.where(magInRange)

    # Get lists of the unique objects and visits:
    uniqObj = groupViewInMagRange.ids
    uniqVisits = set()
    for id in uniqObj:
        for v, f in zip(groupViewInMagRange[id].get('visit'),
                        groupViewInMagRange[id].get('filt')):
            if f == band:
                uniqVisits.add(v)

    uniqVisits = list(uniqVisits)

    if not isinstance(refVisit, int):
        refVisit = int(refVisit)

    if refVisit in uniqVisits:
        # Remove the reference visit from the set of visits:
        uniqVisits.remove(refVisit)

    rmsDistances = list()

    # Loop over visits, calculating the RMS for each:
    for vis in uniqVisits:

        distancesVisit = list()

        for obj in uniqObj:
            visMatch = np.where(groupViewInMagRange[obj].get('visit') == vis)
            refMatch = np.where(groupViewInMagRange[obj].get('visit') == refVisit)

            raObj = groupViewInMagRange[obj].get('coord_ra')
            decObj = groupViewInMagRange[obj].get('coord_dec')

            # Require it to have a match in both the reference and visit image:
            if np.size(visMatch[0]) > 0 and np.size(refMatch[0]) > 0:
                distances = sphDist(raObj[refMatch], decObj[refMatch],
                                    raObj[visMatch], decObj[visMatch])

                distancesVisit.append(distances)

        finiteEntries = np.where(np.isfinite(distancesVisit))[0]
        # Need at least 2 distances to get a finite sample stdev
        if len(finiteEntries) > 1:
            # Calculate the RMS of these offsets:
            # ddof=1 to get sample standard deviation (e.g., 1/(n-1))
            pos_rms_rad = np.std(np.array(distancesVisit)[finiteEntries], ddof=1)
            pos_rms_mas = geom.radToMas(pos_rms_rad)  # milliarcsec
            rmsDistances.append(pos_rms_mas)

        else:
            rmsDistances.append(np.nan)

    rmsDistances = np.array(rmsDistances) * u.marcsec
    return rmsDistances