def testProperMotionMetric(self): """ Test the ProperMotion metric. """ names = [ 'expMJD', 'finSeeing', 'fiveSigmaDepth', 'fieldRA', 'fieldDec', 'filter' ] types = [float, float, float, float, float, '<U1'] data = np.zeros(700, dtype=list(zip(names, types))) slicePoint = [0] stacker = stackers.ParallaxFactorStacker() normFlags = [False, True] data['expMJD'] = np.arange(700) + 56762 data['finSeeing'] = 0.7 data['filter'][0:100] = str('r') data['filter'][100:200] = str('u') data['filter'][200:] = str('g') data['fiveSigmaDepth'] = 24. data = stacker.run(data) for flag in normFlags: data['finSeeing'] = 0.7 data['fiveSigmaDepth'] = 24 baseline = metrics.ProperMotionMetric(normalize=flag, seeingCol='finSeeing').run( data, slicePoint) data['finSeeing'] = data['finSeeing'] + .3 worse1 = metrics.ProperMotionMetric(normalize=flag, seeingCol='finSeeing').run( data, slicePoint) worse2 = metrics.ProperMotionMetric(normalize=flag, rmag=22., seeingCol='finSeeing').run( data, slicePoint) worse3 = metrics.ProperMotionMetric(normalize=flag, rmag=22., seeingCol='finSeeing').run( data[0:300], slicePoint) data['fiveSigmaDepth'] = data['fiveSigmaDepth'] - 1. worse4 = metrics.ProperMotionMetric(normalize=flag, rmag=22., seeingCol='finSeeing').run( data[0:300], slicePoint) # Make sure the RMS increases as seeing increases, the star gets fainter, # the background gets brighter, or the baseline decreases. if flag: # When normalized, mag of star and m5 don't matter (just scheduling). self.assertAlmostEqual(worse2, worse1) self.assertAlmostEqual(worse4, worse3) # But using fewer points should make proper motion worse. # survey assumed to have same seeing and limiting mags. assert (worse3 < worse2) else: assert (worse1 > baseline) assert (worse2 > worse1) assert (worse3 > worse2) assert (worse4 > worse3)
def testParallaxMetric(self): """ Test the parallax metric. """ names = [ 'expMJD', 'finSeeing', 'fiveSigmaDepth', 'fieldRA', 'fieldDec', 'filter' ] types = [float, float, float, float, float, '|S1'] data = np.zeros(700, dtype=zip(names, types)) slicePoint = {'sid': 0} data['expMJD'] = np.arange(700) + 56762 data['finSeeing'] = 0.7 data['filter'][0:100] = 'r' data['filter'][100:200] = 'u' data['filter'][200:] = 'g' data['fiveSigmaDepth'] = 24. stacker = stackers.ParallaxFactorStacker() data = stacker.run(data) normFlags = [False, True] for flag in normFlags: data['finSeeing'] = 0.7 data['fiveSigmaDepth'] = 24. baseline = metrics.ParallaxMetric(normalize=flag, seeingCol='finSeeing').run( data, slicePoint) data['finSeeing'] = data['finSeeing'] + .3 worse1 = metrics.ParallaxMetric(normalize=flag, seeingCol='finSeeing').run( data, slicePoint) worse2 = metrics.ParallaxMetric(normalize=flag, rmag=22., seeingCol='finSeeing').run( data, slicePoint) worse3 = metrics.ParallaxMetric(normalize=flag, rmag=22., seeingCol='finSeeing').run( data[0:300], slicePoint) data['fiveSigmaDepth'] = data['fiveSigmaDepth'] - 1. worse4 = metrics.ParallaxMetric(normalize=flag, rmag=22., seeingCol='finSeeing').run( data[0:300], slicePoint) # Make sure the RMS increases as seeing increases, the star gets fainter, # the background gets brighter, or the baseline decreases. if flag: pass # hmm, I need to think how to test the scheduling #assert(worse1 < baseline) #assert(worse2 < worse1) #assert(worse3 < worse2) #assert(worse4 < worse3) else: assert (worse1 > baseline) assert (worse2 > worse1) assert (worse3 > worse2) assert (worse4 > worse3)
def testEQ(self): """ Test that stackers can be compared """ s1 = stackers.ParallaxFactorStacker() s2 = stackers.ParallaxFactorStacker() assert (s1 == s2) s1 = stackers.RandomDitherFieldPerVisitStacker() s2 = stackers.RandomDitherFieldPerVisitStacker() assert (s1 == s2) # Test if they have numpy array atributes s1.ack = np.arange(10) s2.ack = np.arange(10) assert (s1 == s2) # Change the array and test s1.ack += 1 assert (s1 != s2) s2 = stackers.RandomDitherFieldPerVisitStacker(decCol='blah') assert (s1 != s2)
def testParallaxFactor(self): """ Test the parallax factor. """ data = np.zeros(600, dtype=zip(['fieldRA', 'fieldDec', 'expMJD'], [float, float, float])) data['fieldRA'] = data['fieldRA'] + .1 data['fieldDec'] = data['fieldDec'] - .1 data['expMJD'] = np.arange(data.size) + 49000. stacker = stackers.ParallaxFactorStacker() data = stacker.run(data) self.assertLess(max(np.abs(data['ra_pi_amp'])), 1.1) self.assertLess(max(np.abs(data['dec_pi_amp'])), 1.1) self.assertLess( np.max(data['ra_pi_amp']**2 + data['dec_pi_amp']**2), 1.1) self.assertGreater(min(np.abs(data['ra_pi_amp'])), 0.) self.assertGreater(min(np.abs(data['dec_pi_amp'])), 0.)
def astrometryBatch(colmap=None, runName='opsim', extraSql=None, extraMetadata=None, nside=64, ditherStacker=None, ditherkwargs=None): """Metrics for evaluating proper motion and parallax. Parameters ---------- colmap : dict or None, opt A dictionary with a mapping of column names. Default will use OpsimV4 column names. runName : str, opt The name of the simulated survey. Default is "opsim". nside : int, opt Nside for the healpix slicer. Default 64. extraSql : str or None, opt Additional sql constraint to apply to all metrics. extraMetadata : str or None, opt Additional metadata to apply to all results. ditherStacker: str or lsst.sims.maf.stackers.BaseDitherStacker Optional dither stacker to use to define ra/dec columns. ditherkwargs: dict, opt Optional dictionary of kwargs for the dither stacker. Returns ------- metricBundleDict """ if colmap is None: colmap = ColMapDict('opsimV4') bundleList = [] sql = '' metadata = 'All visits' # Add additional sql constraint (such as wfdWhere) and metadata, if provided. if (extraSql is not None) and (len(extraSql) > 0): sql = extraSql if extraMetadata is None: metadata = extraSql.replace('filter =', '').replace('filter=', '') metadata = metadata.replace('"', '').replace("'", '') if extraMetadata is not None: metadata = extraMetadata subgroup = metadata raCol, decCol, degrees, ditherStacker, ditherMeta = radecCols( ditherStacker, colmap, ditherkwargs) # Don't want dither info in subgroup (too long), but do want it in bundle name. metadata = combineMetadata(metadata, ditherMeta) rmags_para = [22.4, 24.0] rmags_pm = [20.5, 24.0] # Set up parallax/dcr stackers. parallaxStacker = stackers.ParallaxFactorStacker(raCol=raCol, decCol=decCol, dateCol=colmap['mjd'], degrees=degrees) dcrStacker = stackers.DcrStacker(filterCol=colmap['filter'], altCol=colmap['alt'], degrees=degrees, raCol=raCol, decCol=decCol, lstCol=colmap['lst'], site='LSST', mjdCol=colmap['mjd']) # Set up parallax metrics. slicer = slicers.HealpixSlicer(nside=nside, lonCol=raCol, latCol=decCol, latLonDeg=degrees) subsetPlots = [plots.HealpixSkyMap(), plots.HealpixHistogram()] displayDict = { 'group': 'Parallax', 'subgroup': subgroup, 'order': 0, 'caption': None } # Expected error on parallax at 10 AU. plotmaxVals = (2.0, 15.0) for rmag, plotmax in zip(rmags_para, plotmaxVals): plotDict = { 'xMin': 0, 'xMax': plotmax, 'colorMin': 0, 'colorMax': plotmax } metric = metrics.ParallaxMetric(metricName='Parallax Error @ %.1f' % (rmag), rmag=rmag, seeingCol=colmap['seeingGeom'], filterCol=colmap['filter'], m5Col=colmap['fiveSigmaDepth'], normalize=False) bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, stackerList=[parallaxStacker, ditherStacker], displayDict=displayDict, plotDict=plotDict, summaryMetrics=standardSummary(), plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # Parallax normalized to 'best possible' if all visits separated by 6 months. # This separates the effect of cadence from depth. for rmag in rmags_para: metric = metrics.ParallaxMetric( metricName='Normalized Parallax @ %.1f' % (rmag), rmag=rmag, seeingCol=colmap['seeingGeom'], filterCol=colmap['filter'], m5Col=colmap['fiveSigmaDepth'], normalize=True) bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, stackerList=[parallaxStacker, ditherStacker], displayDict=displayDict, summaryMetrics=standardSummary(), plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # Parallax factor coverage. for rmag in rmags_para: metric = metrics.ParallaxCoverageMetric( metricName='Parallax Coverage @ %.1f' % (rmag), rmag=rmag, m5Col=colmap['fiveSigmaDepth'], mjdCol=colmap['mjd'], filterCol=colmap['filter'], seeingCol=colmap['seeingGeom']) bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, stackerList=[parallaxStacker, ditherStacker], displayDict=displayDict, summaryMetrics=standardSummary(), plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # Parallax problems can be caused by HA and DCR degeneracies. Check their correlation. for rmag in rmags_para: metric = metrics.ParallaxDcrDegenMetric( metricName='Parallax-DCR degeneracy @ %.1f' % (rmag), rmag=rmag, seeingCol=colmap['seeingEff'], filterCol=colmap['filter'], m5Col=colmap['fiveSigmaDepth']) caption = 'Correlation between parallax offset magnitude and hour angle for a r=%.1f star.' % ( rmag) caption += ' (0 is good, near -1 or 1 is bad).' bundle = mb.MetricBundle( metric, slicer, sql, metadata=metadata, stackerList=[dcrStacker, parallaxStacker, ditherStacker], displayDict=displayDict, summaryMetrics=standardSummary(), plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # Proper Motion metrics. displayDict = { 'group': 'Proper Motion', 'subgroup': subgroup, 'order': 0, 'caption': None } # Proper motion errors. plotmaxVals = (1.0, 5.0) for rmag, plotmax in zip(rmags_pm, plotmaxVals): plotDict = { 'xMin': 0, 'xMax': plotmax, 'colorMin': 0, 'colorMax': plotmax } metric = metrics.ProperMotionMetric( metricName='Proper Motion Error @ %.1f' % rmag, rmag=rmag, m5Col=colmap['fiveSigmaDepth'], mjdCol=colmap['mjd'], filterCol=colmap['filter'], seeingCol=colmap['seeingGeom'], normalize=False) bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, stackerList=[ditherStacker], displayDict=displayDict, plotDict=plotDict, summaryMetrics=standardSummary(), plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # Normalized proper motion. for rmag in rmags_pm: metric = metrics.ProperMotionMetric( metricName='Normalized Proper Motion @ %.1f' % rmag, rmag=rmag, m5Col=colmap['fiveSigmaDepth'], mjdCol=colmap['mjd'], filterCol=colmap['filter'], seeingCol=colmap['seeingGeom'], normalize=True) bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, stackerList=[ditherStacker], displayDict=displayDict, summaryMetrics=standardSummary(), plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # Set the runName for all bundles and return the bundleDict. for b in bundleList: b.setRunName(runName) return mb.makeBundlesDictFromList(bundleList)
def glanceBatch(colmap=None, runName='opsim', nside=64, filternames=('u', 'g', 'r', 'i', 'z', 'y'), nyears=10, pairnside=32, sqlConstraint=None): """Generate a handy set of metrics that give a quick overview of how well a survey performed. This is a meta-set of other batches, to some extent. Parameters ---------- colmap : dict, opt A dictionary with a mapping of column names. Default will use OpsimV4 column names. run_name : str, opt The name of the simulated survey. Default is "opsim". nside : int, opt The nside for the healpix slicers. Default 64. filternames : list of str, opt The list of individual filters to use when running metrics. Default is ('u', 'g', 'r', 'i', 'z', 'y'). There is always an all-visits version of the metrics run as well. nyears : int (10) How many years to attempt to make hourglass plots for pairnside : int (32) nside to use for the pair fraction metric (it's slow, so nice to use lower resolution) sqlConstraint : str or None, opt Additional SQL constraint to apply to all metrics. Returns ------- metricBundleDict """ if isinstance(colmap, str): raise ValueError('colmap must be a dictionary, not a string') if colmap is None: colmap = ColMapDict('opsimV4') bundleList = [] if sqlConstraint is None: sqlC = '' else: sqlC = '(%s) and' % sqlConstraint sql_per_filt = [ '%s %s="%s"' % (sqlC, colmap['filter'], filtername) for filtername in filternames ] sql_per_and_all_filters = [sqlConstraint] + sql_per_filt standardStats = standardSummary() subsetPlots = [plots.HealpixSkyMap(), plots.HealpixHistogram()] # Super basic things displayDict = {'group': 'Basic Stats', 'order': 1} sql = sqlConstraint slicer = slicers.UniSlicer() # Length of Survey metric = metrics.FullRangeMetric(col=colmap['mjd'], metricName='Length of Survey (days)') bundle = metricBundles.MetricBundle(metric, slicer, sql, displayDict=displayDict) bundleList.append(bundle) # Total number of filter changes metric = metrics.NChangesMetric(col=colmap['filter'], orderBy=colmap['mjd']) bundle = metricBundles.MetricBundle(metric, slicer, sql, displayDict=displayDict) bundleList.append(bundle) # Total open shutter fraction metric = metrics.OpenShutterFractionMetric( slewTimeCol=colmap['slewtime'], expTimeCol=colmap['exptime'], visitTimeCol=colmap['visittime']) bundle = metricBundles.MetricBundle(metric, slicer, sql, displayDict=displayDict) bundleList.append(bundle) # Total effective exposure time metric = metrics.TeffMetric(m5Col=colmap['fiveSigmaDepth'], filterCol=colmap['filter'], normed=True) for sql in sql_per_and_all_filters: bundle = metricBundles.MetricBundle(metric, slicer, sql, displayDict=displayDict) bundleList.append(bundle) # Number of observations, all and each filter metric = metrics.CountMetric(col=colmap['mjd'], metricName='Number of Exposures') for sql in sql_per_and_all_filters: bundle = metricBundles.MetricBundle(metric, slicer, sql, displayDict=displayDict) bundleList.append(bundle) # The alt/az plots of all the pointings slicer = slicers.HealpixSlicer(nside=nside, latCol='zenithDistance', lonCol=colmap['az'], latLonDeg=colmap['raDecDeg'], useCache=False) stacker = stackers.ZenithDistStacker(altCol=colmap['alt'], degrees=colmap['raDecDeg']) metric = metrics.CountMetric(colmap['mjd'], metricName='Nvisits as function of Alt/Az') plotFuncs = [plots.LambertSkyMap()] for sql in sql_per_and_all_filters: bundle = metricBundles.MetricBundle(metric, slicer, sql, plotFuncs=plotFuncs, displayDict=displayDict, stackerList=[stacker]) bundleList.append(bundle) # Things to check per night # Open Shutter per night displayDict = {'group': 'Pointing Efficency', 'order': 2} slicer = slicers.OneDSlicer(sliceColName=colmap['night'], binsize=1) metric = metrics.OpenShutterFractionMetric( slewTimeCol=colmap['slewtime'], expTimeCol=colmap['exptime'], visitTimeCol=colmap['visittime']) sql = sqlConstraint bundle = metricBundles.MetricBundle(metric, slicer, sql, summaryMetrics=standardStats, displayDict=displayDict) bundleList.append(bundle) # Number of filter changes per night slicer = slicers.OneDSlicer(sliceColName=colmap['night'], binsize=1) metric = metrics.NChangesMetric(col=colmap['filter'], orderBy=colmap['mjd'], metricName='Filter Changes') bundle = metricBundles.MetricBundle(metric, slicer, sql, summaryMetrics=standardStats, displayDict=displayDict) bundleList.append(bundle) # A few basic maps # Number of observations, coadded depths displayDict = {'group': 'Basic Maps', 'order': 3} slicer = slicers.HealpixSlicer(nside=nside, latCol=colmap['dec'], lonCol=colmap['ra'], latLonDeg=colmap['raDecDeg']) metric = metrics.CountMetric(col=colmap['mjd']) plotDict = {'percentileClip': 95.} for sql in sql_per_and_all_filters: bundle = metricBundles.MetricBundle(metric, slicer, sql, summaryMetrics=standardStats, displayDict=displayDict, plotDict=plotDict) bundleList.append(bundle) metric = metrics.Coaddm5Metric(m5Col=colmap['fiveSigmaDepth']) for sql in sql_per_and_all_filters: bundle = metricBundles.MetricBundle(metric, slicer, sql, summaryMetrics=standardStats, displayDict=displayDict) bundleList.append(bundle) # Checking a few basic science things # Maybe check astrometry, observation pairs, SN plotDict = {'percentileClip': 95.} displayDict = {'group': 'Science', 'subgroup': 'Astrometry', 'order': 4} stackerList = [] stacker = stackers.ParallaxFactorStacker(raCol=colmap['ra'], decCol=colmap['dec'], degrees=colmap['raDecDeg'], dateCol=colmap['mjd']) stackerList.append(stacker) # Maybe parallax and proper motion, fraction of visits in a good pair for SS displayDict['caption'] = r'Parallax precision of an $r=20$ flat SED star' metric = metrics.ParallaxMetric(m5Col=colmap['fiveSigmaDepth'], filterCol=colmap['filter'], seeingCol=colmap['seeingGeom']) sql = sqlConstraint bundle = metricBundles.MetricBundle(metric, slicer, sql, plotFuncs=subsetPlots, displayDict=displayDict, stackerList=stackerList, plotDict=plotDict) bundleList.append(bundle) displayDict[ 'caption'] = r'Proper motion precision of an $r=20$ flat SED star' metric = metrics.ProperMotionMetric(m5Col=colmap['fiveSigmaDepth'], mjdCol=colmap['mjd'], filterCol=colmap['filter'], seeingCol=colmap['seeingGeom']) bundle = metricBundles.MetricBundle(metric, slicer, sql, plotFuncs=subsetPlots, displayDict=displayDict, plotDict=plotDict) bundleList.append(bundle) # Solar system stuff displayDict['caption'] = 'Fraction of observations that are in pairs' displayDict['subgroup'] = 'Solar System' sql = '%s (filter="g" or filter="r" or filter="i")' % sqlC pairSlicer = slicers.HealpixSlicer(nside=pairnside, latCol=colmap['dec'], lonCol=colmap['ra'], latLonDeg=colmap['raDecDeg']) metric = metrics.PairFractionMetric(mjdCol=colmap['mjd']) bundle = metricBundles.MetricBundle(metric, pairSlicer, sql, plotFuncs=subsetPlots, displayDict=displayDict) bundleList.append(bundle) # stats from the note column if 'note' in colmap.keys(): displayDict = {'group': 'Basic Stats', 'subgroup': 'Percent stats'} metric = metrics.StringCountMetric(col=colmap['note'], percent=True, metricName='Percents') sql = '' slicer = slicers.UniSlicer() bundle = metricBundles.MetricBundle(metric, slicer, sql, displayDict=displayDict) bundleList.append(bundle) displayDict['subgroup'] = 'Count Stats' metric = metrics.StringCountMetric(col=colmap['note'], metricName='Counts') bundle = metricBundles.MetricBundle(metric, slicer, sql, displayDict=displayDict) bundleList.append(bundle) for b in bundleList: b.setRunName(runName) # Add hourglass plots. hrDict = hourglassBatch(colmap=colmap, runName=runName, nyears=nyears, extraSql=sqlConstraint) # Add basic slew stats. try: slewDict = slewBasics(colmap=colmap, runName=runName) except KeyError as e: warnings.warn( 'Could not add slew stats: missing required key %s from colmap' % (e)) bd = metricBundles.makeBundlesDictFromList(bundleList) bd.update(slewDict) bd.update(hrDict) return bd
def testBaseDitherStacker(self): # Test that the base dither stacker matches the type of a stacker. s = stackers.HexDitherFieldPerNightStacker() self.assertTrue(isinstance(s, stackers.BaseDitherStacker)) s = stackers.ParallaxFactorStacker() self.assertFalse(isinstance(s, stackers.BaseDitherStacker))
def astrometryBatch(colmap=None, runName='opsim', extraSql=None, extraMetadata=None, nside=64): # Allow user to add dithering. if colmap is None: colmap = ColMapDict('opsimV4') bundleList = [] sql = '' metadata = 'All visits' # Add additional sql constraint (such as wfdWhere) and metadata, if provided. if (extraSql is not None) and (len(extraSql) > 0): sql = extraSql if extraMetadata is None: metadata = extraSql.replace('filter =', '').replace('filter=', '') metadata = metadata.replace('"', '').replace("'", '') if extraMetadata is not None: metadata = extraMetadata subgroup = metadata raCol = colmap['ra'] decCol = colmap['dec'] degrees = colmap['raDecDeg'] # Set up stackers. parallaxStacker = stackers.ParallaxFactorStacker(raCol=raCol, decCol=decCol, dateCol=colmap['mjd'], degrees=degrees) dcrStacker = stackers.DcrStacker(filterCol=colmap['filter'], altCol=colmap['alt'], degrees=degrees, raCol=raCol, decCol=decCol, lstCol=colmap['lst'], site='LSST', mjdCol=colmap['mjd']) # Set up parallax metrics. slicer = slicers.HealpixSlicer(nside=nside, lonCol=raCol, latCol=decCol, latLonDeg=degrees) subsetPlots = [plots.HealpixSkyMap(), plots.HealpixHistogram()] displayDict = {'group': 'Parallax', 'subgroup': subgroup, 'order': 0, 'caption': None} # Expected error on parallax at 10 AU. for rmag in (20.0, 24.0): metric = metrics.ParallaxMetric(metricName='Parallax @ %.1f' % (rmag), rmag=rmag, seeingCol=colmap['seeingGeom'], filterCol=colmap['filter'], m5Col=colmap['fiveSigmaDepth'], normalize=False) bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, stackerList=[parallaxStacker], displayDict=displayDict, summaryMetrics=standardSummary(), plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # Parallax normalized to 'best possible' if all visits separated by 6 months. # This separates the effect of cadence from depth. for rmag in (20.0, 24.0): metric = metrics.ParallaxMetric(metricName='Normalized Parallax @ %.1f' % (rmag), rmag=rmag, seeingCol=colmap['seeingGeom'], filterCol=colmap['filter'], m5Col=colmap['fiveSigmaDepth'], normalize=True) bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, stackerList=[parallaxStacker], displayDict=displayDict, summaryMetrics=standardSummary(), plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # Parallax factor coverage. for rmag in (20.0, 24.0): metric = metrics.ParallaxCoverageMetric(metricName='Parallax Coverage @ %.1f' % (rmag), rmag=rmag, m5Col=colmap['fiveSigmaDepth'], mjdCol=colmap['mjd'], filterCol=colmap['filter'], seeingCol=colmap['seeingGeom']) bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, stackerList=[parallaxStacker], displayDict=displayDict, summaryMetrics=standardSummary(), plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # Parallax problems can be caused by HA and DCR degeneracies. Check their correlation. for rmag in (20.0, 24.0): metric = metrics.ParallaxDcrDegenMetric(metricName='Parallax-DCR degeneracy @ %.1f' % (rmag), rmag=rmag, seeingCol=colmap['seeingEff'], filterCol=colmap['filter'], m5Col=colmap['fiveSigmaDepth']) caption = 'Correlation between parallax offset magnitude and hour angle for a r=%.1f star.' % (rmag) caption += ' (0 is good, near -1 or 1 is bad).' bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, stackerList=[dcrStacker, parallaxStacker], displayDict=displayDict, summaryMetrics=standardSummary(), plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # Proper Motion metrics. displayDict = {'group': 'Proper Motion', 'subgroup': subgroup, 'order': 0, 'caption': None} # Proper motion errors. for rmag in (20.0, 24.0): metric = metrics.ProperMotionMetric(metricName='Proper Motion %.1f' % rmag, rmag=rmag, m5Col=colmap['fiveSigmaDepth'], mjdCol=colmap['mjd'], filterCol=colmap['filter'], seeingCol=colmap['seeingGeom'], normalize=False) bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, displayDict=displayDict, summaryMetrics=standardSummary(), plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # Normalized proper motion. for rmag in (20.0, 24.0): metric = metrics.ProperMotionMetric(metricName='Normalized Proper Motion %.1f' % rmag, rmag=rmag, m5Col=colmap['fiveSigmaDepth'], mjdCol=colmap['mjd'], filterCol=colmap['filter'], seeingCol=colmap['seeingGeom'], normalize=True) bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, displayDict=displayDict, summaryMetrics=standardSummary(), plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # Set the runName for all bundles and return the bundleDict. for b in bundleList: b.setRunName(runName) return mb.makeBundlesDictFromList(bundleList)