Coverage for python/lsst/sims/maf/batches/movingObjectsBatch.py : 4%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from __future__ import print_function, division
2from copy import deepcopy
3import os
4import numpy as np
5import numpy.ma as ma
6import matplotlib.pyplot as plt
7import lsst.sims.maf.metrics as metrics
8import lsst.sims.maf.slicers as slicers
9import lsst.sims.maf.stackers as stackers
10import lsst.sims.maf.plots as plots
11import lsst.sims.maf.metricBundles as mb
12from .colMapDict import ColMapDict
13from .common import summaryCompletenessAtTime, summaryCompletenessOverH, fractionPopulationAtThreshold
15__all__ = ['defaultHrange', 'defaultCharacterization','setupMoSlicer',
16 'quickDiscoveryBatch', 'discoveryBatch',
17 'runCompletenessSummary', 'plotCompleteness',
18 'characterizationInnerBatch', 'characterizationOuterBatch',
19 'runFractionSummary', 'plotFractions',
20 'plotSingle', 'plotActivity',
21 'readAndCombine', 'combineSubsets']
24def defaultHrange(metadata):
25 "Provide useful default ranges for H, based on metadata of population type."
26 defaultRanges = {'PHA': [16, 28, 0.2],
27 'NEO': [16, 28, 0.2],
28 'MBA': [16, 26, 0.2],
29 'Trojan': [14, 22, 0.2],
30 'TNO': [4, 12, 0.2],
31 'SDO': [4, 12, 0.2]}
32 defaultHmark = {'PHA': 22, 'NEO': 22, 'MBA': 20,
33 'Trojan': 18, 'TNO': 8, 'SDO': 8}
34 if metadata in defaultRanges:
35 Hrange = defaultRanges[metadata]
36 Hmark = defaultHmark[metadata]
37 elif metadata.upper().startswith('GRANVIK'):
38 Hrange = defaultRanges['NEO']
39 Hmark = defaultHmark['NEO']
40 elif metadata.upper().startswith('L7'):
41 Hrange = defaultRanges('TNO')
42 Hmark = defaultHmark['TNO']
43 else:
44 print(f'## Could not find {metadata} in default keys ({defaultRanges.keys()}). \n'
45 f'## Using expanded default range instead.')
46 Hrange = [4, 28, 0.5]
47 Hmark = 10
48 return Hrange, Hmark
51def defaultCharacterization(metadata):
52 "Provide useful characterization bundle type, based on metadata of population type."
53 defaultChar = {'PHA': 'inner', 'NEO': 'inner',
54 'MBA': 'inner', 'Trojan': 'inner',
55 'TNO': 'outer', 'SDO': 'outer'}
56 if metadata in defaultChar:
57 char = defaultChar[metadata]
58 elif metadata.upper().startswith('GRANVIK'):
59 char = 'inner'
60 elif metadata.upper().startswith('L7'):
61 char = 'outer'
62 else:
63 print(f'## Could not find {metadata} in default keys ({defaultChar.keys()}). \n'
64 f'## Using Inner (Asteroid) characterization by default.')
65 char = 'inner'
66 return char
69def setupMoSlicer(orbitFile, Hrange, obsFile=None):
70 """
71 Set up the slicer and read orbitFile and obsFile from disk.
73 Parameters
74 ----------
75 orbitFile : str
76 The file containing the orbit information.
77 Hrange : numpy.ndarray or None
78 The Hrange parameter to pass to slicer.readOrbits
79 obsFile : str, optional
80 The file containing the observations of each object, optional.
81 If not provided (default, None), then the slicer will not be able to 'slice', but can still plot.
83 Returns
84 -------
85 ~lsst.sims.maf.slicer.MoObjSlicer
86 """
87 # Read the orbit file and set the H values for the slicer.
88 slicer = slicers.MoObjSlicer(Hrange=Hrange)
89 slicer.setupSlicer(orbitFile=orbitFile, obsFile=obsFile)
90 return slicer
93def quickDiscoveryBatch(slicer, colmap=None, runName='opsim', detectionLosses='detection', metadata='',
94 albedo=None, Hmark=None, npReduce=np.mean, constraint=None):
95 if colmap is None:
96 colmap = ColMapDict('opsimV4')
97 bundleList = []
98 plotBundles = []
100 basicPlotDict = {'albedo': albedo, 'Hmark': Hmark, 'npReduce': npReduce,
101 'nxbins': 200, 'nybins': 200}
102 plotFuncs = [plots.MetricVsH()]
103 displayDict ={'group': 'Discovery'}
105 if detectionLosses not in ('detection', 'trailing'):
106 raise ValueError('Please choose detection or trailing as options for detectionLosses.')
107 if detectionLosses == 'trailing':
108 magStacker = stackers.MoMagStacker(lossCol='dmagTrail')
109 detectionLosses = ' trailing loss'
110 else:
111 magStacker = stackers.MoMagStacker(lossCol='dmagDetect')
112 detectionLosses = ' detection loss'
114 # Set up a dictionary to pass to each metric for the column names.
115 colkwargs = {'mjdCol': colmap['mjd'], 'seeingCol': colmap['seeingGeom'],
116 'expTimeCol': colmap['exptime'], 'm5Col': colmap['fiveSigmaDepth'],
117 'nightCol': colmap['night'], 'filterCol': colmap['filter']}
119 def _setup_child_metrics(parentMetric):
120 childMetrics = {}
121 childMetrics['Time'] = metrics.Discovery_TimeMetric(parentMetric, **colkwargs)
122 childMetrics['N_Chances'] = metrics.Discovery_N_ChancesMetric(parentMetric, **colkwargs)
123 # Could expand to add N_chances per year, but not really necessary.
124 return childMetrics
126 def _configure_child_bundles(parentBundle):
127 dispDict = {'group': 'Discovery', 'subgroup': 'Time',
128 'caption': 'Time of discovery of objects', 'order': 0}
129 parentBundle.childBundles['Time'].setDisplayDict(dispDict)
130 dispDict = {'group': 'Discovery', 'subgroup': 'NChances',
131 'caption': 'Number of chances for discovery of objects', 'order': 0}
132 parentBundle.childBundles['N_Chances'].setDisplayDict(dispDict)
133 return
135 # 3 pairs in 15
136 md = metadata + ' 3 pairs in 15 nights' + detectionLosses
137 # Set up plot dict.
138 plotDict = {'title': '%s: %s' % (runName, md)}
139 plotDict.update(basicPlotDict)
140 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90./60./24.,
141 nNightsPerWindow=3, tWindow=15, **colkwargs)
142 childMetrics = _setup_child_metrics(metric)
143 bundle = mb.MoMetricBundle(metric, slicer, constraint,
144 stackerList=[magStacker],
145 runName=runName, metadata=md,
146 childMetrics=childMetrics,
147 plotDict=plotDict, plotFuncs=plotFuncs,
148 displayDict=displayDict)
149 _configure_child_bundles(bundle)
150 bundleList.append(bundle)
152 # 3 pairs in 30
153 md = metadata + ' 3 pairs in 30 nights' + detectionLosses
154 plotDict = {'title': '%s: %s' % (runName, md)}
155 plotDict.update(basicPlotDict)
156 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90. / 60. / 24.,
157 nNightsPerWindow=3, tWindow=30, **colkwargs)
158 childMetrics = _setup_child_metrics(metric)
159 bundle = mb.MoMetricBundle(metric, slicer, constraint,
160 stackerList=[magStacker],
161 runName=runName, metadata=md,
162 childMetrics=childMetrics,
163 plotDict=plotDict, plotFuncs=plotFuncs,
164 displayDict=displayDict)
165 _configure_child_bundles(bundle)
166 bundleList.append(bundle)
168 # Set the runName for all bundles and return the bundleDict.
169 for b in bundleList:
170 b.setRunName(runName)
171 return mb.makeBundlesDictFromList(bundleList), plotBundles
174def discoveryBatch(slicer, colmap=None, runName='opsim', detectionLosses='detection', metadata='',
175 albedo=None, Hmark=None, npReduce=np.mean, constraint=None):
176 if colmap is None:
177 colmap = ColMapDict('opsimV4')
178 bundleList = []
179 plotBundles = []
181 basicPlotDict = {'albedo': albedo, 'Hmark': Hmark, 'npReduce': npReduce,
182 'nxbins': 200, 'nybins': 200}
183 plotFuncs = [plots.MetricVsH()]
184 displayDict ={'group': 'Discovery'}
186 if detectionLosses not in ('detection', 'trailing'):
187 raise ValueError('Please choose detection or trailing as options for detectionLosses.')
188 if detectionLosses == 'trailing':
189 # These are the SNR-losses only.
190 magStacker = stackers.MoMagStacker(lossCol='dmagTrail')
191 detectionLosses = ' trailing loss'
192 else:
193 # This is SNR losses, plus additional loss due to detecting with stellar PSF.
194 magStacker = stackers.MoMagStacker(lossCol='dmagDetect')
195 detectionLosses = ' detection loss'
197 # Set up a dictionary to pass to each metric for the column names.
198 colkwargs = {'mjdCol': colmap['mjd'], 'seeingCol': colmap['seeingGeom'],
199 'expTimeCol': colmap['exptime'], 'm5Col': colmap['fiveSigmaDepth'],
200 'nightCol': colmap['night'], 'filterCol': colmap['filter']}
202 def _setup_child_metrics(parentMetric):
203 childMetrics = {}
204 childMetrics['Time'] = metrics.Discovery_TimeMetric(parentMetric, **colkwargs)
205 childMetrics['N_Chances'] = metrics.Discovery_N_ChancesMetric(parentMetric, **colkwargs)
206 # Could expand to add N_chances per year, but not really necessary.
207 return childMetrics
209 def _configure_child_bundles(parentBundle):
210 dispDict = {'group': 'Discovery', 'subgroup': 'Time',
211 'caption': 'Time of discovery of objects', 'order': 0}
212 parentBundle.childBundles['Time'].setDisplayDict(dispDict)
213 dispDict = {'group': 'Discovery', 'subgroup': 'NChances',
214 'caption': 'Number of chances for discovery of objects', 'order': 0}
215 parentBundle.childBundles['N_Chances'].setDisplayDict(dispDict)
216 return
218 # 3 pairs in 15 and 3 pairs in 30 done in 'quickDiscoveryBatch' (with vis).
220 # 3 pairs in 12
221 md = metadata + ' 3 pairs in 12 nights' + detectionLosses
222 plotDict = {'title': '%s: %s' % (runName, md)}
223 plotDict.update(basicPlotDict)
224 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90. / 60. / 24.,
225 nNightsPerWindow=3, tWindow=12, **colkwargs)
226 childMetrics = _setup_child_metrics(metric)
227 bundle = mb.MoMetricBundle(metric, slicer, constraint,
228 stackerList=[magStacker],
229 runName=runName, metadata=md,
230 childMetrics=childMetrics,
231 plotDict=plotDict, plotFuncs=plotFuncs,
232 displayDict=displayDict)
233 _configure_child_bundles(bundle)
234 bundleList.append(bundle)
236 # 3 pairs in 20
237 md = metadata + ' 3 pairs in 20 nights' + detectionLosses
238 plotDict = {'title': '%s: %s' % (runName, md)}
239 plotDict.update(basicPlotDict)
240 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90. / 60. / 24.,
241 nNightsPerWindow=3, tWindow=20, **colkwargs)
242 childMetrics = _setup_child_metrics(metric)
243 bundle = mb.MoMetricBundle(metric, slicer, constraint,
244 stackerList=[magStacker],
245 runName=runName, metadata=md,
246 childMetrics=childMetrics,
247 plotDict=plotDict, plotFuncs=plotFuncs,
248 displayDict=displayDict)
249 _configure_child_bundles(bundle)
250 bundleList.append(bundle)
252 # 3 pairs in 25
253 md = metadata + ' 3 pairs in 25 nights' + detectionLosses
254 plotDict = {'title': '%s: %s' % (runName, md)}
255 plotDict.update(basicPlotDict)
256 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90. / 60. / 24.,
257 nNightsPerWindow=3, tWindow=25, **colkwargs)
258 childMetrics = _setup_child_metrics(metric)
259 bundle = mb.MoMetricBundle(metric, slicer, constraint,
260 stackerList=[magStacker],
261 runName=runName, metadata=md,
262 childMetrics=childMetrics,
263 plotDict=plotDict, plotFuncs=plotFuncs,
264 displayDict=displayDict)
265 _configure_child_bundles(bundle)
266 bundleList.append(bundle)
268 # 4 pairs in 20
269 md = metadata + ' 4 pairs in 20 nights' + detectionLosses
270 plotDict = {'title': '%s: %s' % (runName, md)}
271 plotDict.update(basicPlotDict)
272 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90. / 60. / 24.,
273 nNightsPerWindow=4, tWindow=20, **colkwargs)
274 childMetrics = _setup_child_metrics(metric)
275 bundle = mb.MoMetricBundle(metric, slicer, constraint,
276 stackerList=[magStacker],
277 runName=runName, metadata=md,
278 childMetrics=childMetrics,
279 plotDict=plotDict, plotFuncs=plotFuncs,
280 displayDict=displayDict)
281 _configure_child_bundles(bundle)
282 bundleList.append(bundle)
284 # 3 triplets in 30
285 md = metadata + ' 3 triplets in 30 nights' + detectionLosses
286 plotDict = {'title': '%s: %s' % (runName, md)}
287 plotDict.update(basicPlotDict)
288 metric = metrics.DiscoveryMetric(nObsPerNight=3, tMin=0, tMax=120. / 60. / 24.,
289 nNightsPerWindow=3, tWindow=30, **colkwargs)
290 childMetrics = _setup_child_metrics(metric)
291 bundle = mb.MoMetricBundle(metric, slicer, constraint,
292 stackerList=[magStacker],
293 runName=runName, metadata=md,
294 childMetrics=childMetrics,
295 plotDict=plotDict, plotFuncs=plotFuncs,
296 displayDict=displayDict)
297 _configure_child_bundles(bundle)
298 bundleList.append(bundle)
300 # 3 quads in 30
301 md = metadata + ' 3 quads in 30 nights' + detectionLosses
302 plotDict = {'title': '%s: %s' % (runName, md)}
303 plotDict.update(basicPlotDict)
304 metric = metrics.DiscoveryMetric(nObsPerNight=4, tMin=0, tMax=150. / 60. / 24.,
305 nNightsPerWindow=3, tWindow=30, **colkwargs)
306 childMetrics = _setup_child_metrics(metric)
307 bundle = mb.MoMetricBundle(metric, slicer, constraint,
308 stackerList=[magStacker],
309 runName=runName, metadata=md,
310 childMetrics=childMetrics,
311 plotDict=plotDict, plotFuncs=plotFuncs,
312 displayDict=displayDict)
313 _configure_child_bundles(bundle)
314 bundleList.append(bundle)
316 # Play with SNR.
317 # First standard SNR / probabilistic visibility (SNR~5)
318 # 3 pairs in 15
319 md = metadata + ' 3 pairs in 15 nights SNR=5' + detectionLosses
320 # Set up plot dict.
321 plotDict = {'title': '%s: %s' % (runName, md)}
322 plotDict.update(basicPlotDict)
323 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90./60./24.,
324 nNightsPerWindow=3, tWindow=15, snrLimit=5, **colkwargs)
325 childMetrics = _setup_child_metrics(metric)
326 bundle = mb.MoMetricBundle(metric, slicer, constraint,
327 stackerList=[magStacker],
328 runName=runName, metadata=md,
329 childMetrics=childMetrics,
330 plotDict=plotDict, plotFuncs=plotFuncs,
331 displayDict=displayDict)
332 _configure_child_bundles(bundle)
333 bundleList.append(bundle)
336 # 3 pairs in 15, SNR=4.
337 md = metadata + ' 3 pairs in 15 nights SNR=4' + detectionLosses
338 plotDict = {'title': '%s: %s' % (runName, md)}
339 plotDict.update(basicPlotDict)
340 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90. / 60. / 24.,
341 nNightsPerWindow=3, tWindow=15, snrLimit=4, **colkwargs)
342 childMetrics = _setup_child_metrics(metric)
343 bundle = mb.MoMetricBundle(metric, slicer, constraint,
344 stackerList=[magStacker],
345 runName=runName, metadata=md,
346 childMetrics=childMetrics,
347 plotDict=plotDict, plotFuncs=plotFuncs,
348 displayDict=displayDict)
349 _configure_child_bundles(bundle)
350 bundleList.append(bundle)
352 # 3 pairs in 30, SNR=5
353 md = metadata + ' 3 pairs in 30 nights SNR=5' + detectionLosses
354 plotDict = {'title': '%s: %s' % (runName, md)}
355 plotDict.update(basicPlotDict)
356 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90. / 60. / 24.,
357 nNightsPerWindow=3, tWindow=30, snrLimit=5, **colkwargs)
358 childMetrics = _setup_child_metrics(metric)
359 bundle = mb.MoMetricBundle(metric, slicer, constraint,
360 stackerList=[magStacker],
361 runName=runName, metadata=md,
362 childMetrics=childMetrics,
363 plotDict=plotDict, plotFuncs=plotFuncs,
364 displayDict=displayDict)
365 _configure_child_bundles(bundle)
366 bundleList.append(bundle)
369 # 3 pairs in 30, SNR=4
370 md = metadata + ' 3 pairs in 30 nights SNR=4' + detectionLosses
371 plotDict = {'title': '%s: %s' % (runName, md)}
372 plotDict.update(basicPlotDict)
373 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90. / 60. / 24.,
374 nNightsPerWindow=3, tWindow=30, snrLimit=4, **colkwargs)
375 childMetrics = _setup_child_metrics(metric)
376 bundle = mb.MoMetricBundle(metric, slicer, constraint,
377 stackerList=[magStacker],
378 runName=runName, metadata=md,
379 childMetrics=childMetrics,
380 plotDict=plotDict, plotFuncs=plotFuncs,
381 displayDict=displayDict)
382 _configure_child_bundles(bundle)
383 bundleList.append(bundle)
385 # Play with SNR. SNR=3
386 # 3 pairs in 15, SNR=3
387 md = metadata + ' 3 pairs in 15 nights SNR=3' + detectionLosses
388 plotDict = {'title': '%s: %s' % (runName, md)}
389 plotDict.update(basicPlotDict)
390 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90. / 60. / 24.,
391 nNightsPerWindow=3, tWindow=15, snrLimit=3, **colkwargs)
392 childMetrics = _setup_child_metrics(metric)
393 bundle = mb.MoMetricBundle(metric, slicer, constraint,
394 stackerList=[magStacker],
395 runName=runName, metadata=md,
396 childMetrics=childMetrics,
397 plotDict=plotDict, plotFuncs=plotFuncs,
398 displayDict=displayDict)
399 _configure_child_bundles(bundle)
400 bundleList.append(bundle)
402 # SNR = 0
403 # 3 pairs in 15, SNR=0
404 md = metadata + ' 3 pairs in 15 nights SNR=0' + detectionLosses
405 plotDict = {'title': '%s: %s' % (runName, md)}
406 plotDict.update(basicPlotDict)
407 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90. / 60. / 24.,
408 nNightsPerWindow=3, tWindow=15, snrLimit=0, **colkwargs)
409 childMetrics = _setup_child_metrics(metric)
410 bundle = mb.MoMetricBundle(metric, slicer, constraint,
411 stackerList=[magStacker],
412 runName=runName, metadata=md,
413 childMetrics=childMetrics,
414 plotDict=plotDict, plotFuncs=plotFuncs,
415 displayDict=displayDict)
416 _configure_child_bundles(bundle)
417 bundleList.append(bundle)
419 # Play with weird strategies.
420 # Single detection.
421 md = metadata + ' Single detection' + detectionLosses
422 plotDict = {'title': '%s: %s' % (runName, md)}
423 plotDict.update(basicPlotDict)
424 metric = metrics.DiscoveryMetric(nObsPerNight=1, tMin=0, tMax=90. / 60. / 24.,
425 nNightsPerWindow=1, tWindow=5, **colkwargs)
426 childMetrics = _setup_child_metrics(metric)
427 bundle = mb.MoMetricBundle(metric, slicer, constraint,
428 stackerList=[magStacker],
429 runName=runName, metadata=md,
430 childMetrics=childMetrics,
431 plotDict=plotDict, plotFuncs=plotFuncs,
432 displayDict=displayDict)
433 _configure_child_bundles(bundle)
434 bundleList.append(bundle)
436 # Single pair of detections.
437 md = metadata + ' Single pair' + detectionLosses
438 plotDict = {'title': '%s: %s' % (runName, md)}
439 plotDict.update(basicPlotDict)
440 metric = metrics.DiscoveryMetric(nObsPerNight=2, tMin=0, tMax=90. / 60. / 24.,
441 nNightsPerWindow=1, tWindow=5, **colkwargs)
442 childMetrics = _setup_child_metrics(metric)
443 bundle = mb.MoMetricBundle(metric, slicer, constraint,
444 stackerList=[magStacker],
445 runName=runName, metadata=md,
446 childMetrics=childMetrics,
447 plotDict=plotDict, plotFuncs=plotFuncs,
448 displayDict=displayDict)
449 _configure_child_bundles(bundle)
450 bundleList.append(bundle)
452 # High velocity discovery.
453 displayDict['subgroup'] = 'High Velocity'
455 # High velocity.
456 md = metadata + ' High velocity pair' + detectionLosses
457 plotDict = {'title': '%s: %s' % (runName, md)}
458 plotDict.update(basicPlotDict)
459 metric = metrics.HighVelocityNightsMetric(psfFactor=2., nObsPerNight=2, **colkwargs)
460 bundle = mb.MoMetricBundle(metric, slicer, constraint,
461 stackerList=[magStacker],
462 runName=runName, metadata=md,
463 plotDict=plotDict, plotFuncs=plotFuncs,
464 displayDict=displayDict)
465 bundleList.append(bundle)
467 # "magic" detection - 6 in 60 days.
468 md = metadata + ' 6 detections in 60 nights' + detectionLosses
469 plotDict = {'title': '%s: %s' % (runName, md)}
470 plotDict.update(basicPlotDict)
471 metric = metrics.MagicDiscoveryMetric(nObs=6, tWindow=60, **colkwargs)
472 bundle = mb.MoMetricBundle(metric, slicer, constraint,
473 stackerList=[magStacker],
474 runName=runName, metadata=md,
475 plotDict=plotDict, plotFuncs=plotFuncs,
476 displayDict=displayDict)
477 bundleList.append(bundle)
479 # Set the runName for all bundles and return the bundleDict.
480 for b in bundleList:
481 b.setRunName(runName)
482 return mb.makeBundlesDictFromList(bundleList), plotBundles
485def runCompletenessSummary(bdict, Hmark, times, outDir, resultsDb):
486 """
487 Calculate completeness and create completeness bundles from all N_Chances and Time (child) metrics
488 of the (discovery) bundles in bdict, and write completeness at Hmark to resultsDb, save bundle to disk.
490 This should be done after combining any sub-sets of the metric results.
492 Parameters
493 ----------
494 bdict : dict of metricBundles
495 Dict containing ~lsst.sims.maf.MoMetricBundles,
496 including bundles we're expecting to contain completeness.
497 Hmark : float
498 Hmark value to add to completeness plotting dict.
499 If not defined (None), then the Hmark from the plotdict from the metric will be used if available.
500 If None and Hmark not in plotDict, then median of Hrange value will be used.
501 times : np.ndarray
502 The times at which to calculate completeness (over time).
503 outDir : str
504 Output directory to save completeness bundles to disk.
505 resultsDb : ~lsst.sims.maf.db.ResultsDb
506 Results database to save information about completeness bundle.
508 Returns
509 -------
510 dict of metricBundles
511 A dictionary of the new completeness bundles. Keys match original keys,
512 with additions of "[Differential,Cumulative]Completeness@Time"
513 and "[Differential,Cumulative]Completeness" to distinguish new entries.
514 """
515 # Add completeness bundles and write completeness at Hmark to resultsDb.
516 completeness = {}
517 group = 'Discovery'
518 subgroup = 'Completeness'
520 def _compbundles(b, bundle, Hmark, resultsDb):
521 # Find Hmark if not set (this may be different for different bundles).
522 if Hmark is None and 'Hmark' in bundle.plotDict:
523 Hmark = bundle.plotDict['Hmark']
524 if Hmark is None:
525 Hmark = np.median(bundle.slicer.slicePoints['H'])
526 # Set up the summary metrics.
527 summaryTimeMetrics = summaryCompletenessAtTime(times, Hval=Hmark, Hindex=0.33)
528 summaryTimeMetrics2 = summaryCompletenessAtTime(times, Hval=Hmark - 2, Hindex=0.33)
529 summaryHMetrics = summaryCompletenessOverH(requiredChances=1, Hindex=0.33)
530 comp = {}
531 # Bundle = single metric bundle. Add differential and cumulative completeness.
532 if 'Time' in bundle.metric.name:
533 for metric in summaryTimeMetrics:
534 newkey = b + ' ' + metric.name
535 comp[newkey] = mb.makeCompletenessBundle(bundle, metric,
536 Hmark=None, resultsDb=resultsDb)
537 comp[newkey].plotDict['times'] = times
538 comp[newkey].plotDict['Hval'] = metric.Hval
539 for metric in summaryTimeMetrics2:
540 newkey = b + ' ' + metric.name
541 comp[newkey] = mb.makeCompletenessBundle(bundle, metric,
542 Hmark=None, resultsDb=resultsDb)
543 comp[newkey].plotDict['times'] = times
544 comp[newkey].plotDict['Hval'] = metric.Hval
545 elif 'N_Chances' in bundle.metric.name:
546 for metric in summaryHMetrics:
547 newkey = b + ' ' + metric.name
548 comp[newkey] = mb.makeCompletenessBundle(bundle, metric,
549 Hmark=Hmark, resultsDb=resultsDb)
550 return comp
552 # Generate the completeness bundles for the various discovery metrics.
553 for b, bundle in bdict.items():
554 if 'Discovery' in bundle.metric.name:
555 completeness.update(_compbundles(b, bundle, Hmark, resultsDb))
556 if isinstance(bundle.metric, metrics.HighVelocityNightsMetric):
557 completeness.update(_compbundles(b, bundle, Hmark, resultsDb))
558 if isinstance(bundle.metric, metrics.MagicDiscoveryMetric):
559 completeness.update(_compbundles(b, bundle, Hmark, resultsDb))
561 # Write the completeness bundles to disk, so we can re-read them later.
562 # (also set the display dict properties, for the resultsDb output).
563 for b, bundle in completeness.items():
564 bundle.setDisplayDict({'group': group, 'subgroup': subgroup})
565 bundle.write(outDir=outDir, resultsDb=resultsDb)
567 return completeness
570def plotCompleteness(bdictCompleteness, figroot=None, resultsDb=None,
571 outDir='.', figformat='pdf'):
572 """Plot a minor subset of the completeness results.
573 """
574 # Separate some subsets to plot together.
575 keys = ['3_pairs_in_30_nights_detection_loss',
576 '3_pairs_in_15_nights_detection_loss']
577 plotTimes = {}
578 plotComp = {}
579 plotDiff = {}
580 for k in bdictCompleteness:
581 for key in keys:
582 if key in k:
583 if 'Discovery_Time' in k:
584 if 'Cumulative' in k:
585 plotTimes[k] = bdictCompleteness[k]
586 elif 'Discovery_N_Chances' in k:
587 if 'Differential' in k:
588 plotDiff[k] = bdictCompleteness[k]
589 elif 'Cumulative' in k:
590 plotComp[k] = bdictCompleteness[k]
592 # Add plot dictionaries to code 30 nights red, 15 nights blue, differentials dotted.
593 def _codePlot(key):
594 plotDict = {}
595 if 'Differential' in k:
596 plotDict['linestyle'] = ':'
597 else:
598 plotDict['linestyle'] = '-'
599 if '30_nights' in k:
600 plotDict['color'] = 'r'
601 if '15_nights' in k:
602 plotDict['color'] = 'b'
603 return plotDict
604 # Apply color-coding.
605 for k, b in plotTimes.items():
606 b.setPlotDict(_codePlot(k))
607 for k, b in plotDiff.items():
608 b.setPlotDict(_codePlot(k))
609 for k, b in plotComp.items():
610 b.setPlotDict(_codePlot(k))
612 first = bdictCompleteness[list(bdictCompleteness.keys())[0]]
613 if figroot is None:
614 figroot = first.runName
616 # Plot completeness as a function of time.
617 fig = plt.figure(figsize=(8, 6))
618 for k in plotTimes:
619 plt.plot(plotTimes[k].plotDict['times'], plotTimes[k].metricValues[0, :],
620 label=plotTimes[k].plotDict['label'] + ' @H=%.2f' % plotTimes[k].plotDict['Hval'])
621 plt.legend()
622 plt.xlabel('Time (MJD)')
623 plt.ylabel('Completeness')
624 plt.grid(True, alpha=0.3)
625 # Make a PlotHandler to deal with savings/resultsDb, etc.
626 ph = plots.PlotHandler(figformat=figformat, resultsDb=resultsDb, outDir=outDir)
627 displayDict = {'group': 'Completeness', 'subgroup': 'Over Time',
628 'caption': 'Completeness over time, for H values indicated in legend.'}
629 ph.saveFig(fig.number, f'{figroot}_CompletenessOverTime', 'Combo', 'CompletenessOverTime', 'MoObjSlicer',
630 figroot, None, None, displayDict=displayDict)
632 plt.savefig(os.path.join(outDir, f'{figroot}_CompletenessOverTime.{figformat}'), format=figformat)
634 # Plot cumulative completeness.
635 ph = plots.PlotHandler(figformat=figformat, resultsDb=resultsDb, outDir=outDir)
636 ph.setMetricBundles(plotComp)
637 plotDict = {'ylabel': "Completeness", 'figsize': (8, 6), 'albedo': 0.14}
638 ph.plot(plotFunc=plots.MetricVsH(), plotDicts=plotDict,
639 outfileRoot=figroot + '_CumulativeCompleteness')
641 # Plot differential completeness.
642 ph = plots.PlotHandler(figformat=figformat, resultsDb=resultsDb, outDir=outDir)
643 ph.setMetricBundles(plotDiff)
644 plotDict = {'ylabel': "Completeness", 'figsize': (8, 6)}
645 ph.plot(plotFunc=plots.MetricVsH(), plotDicts=plotDict,
646 outfileRoot=figroot + '_DifferentialCompleteness')
649def characterizationInnerBatch(slicer, colmap=None, runName='opsim', metadata='',
650 albedo=None, Hmark=None, constraint=None, npReduce=np.mean,
651 windows=None, bins=None):
652 """Characterization metrics for inner solar system objects.
653 """
654 if colmap is None:
655 colmap = ColMapDict('opsimV4')
656 bundleList = []
657 plotBundles = []
659 # Set up a dictionary to pass to each metric for the column names.
660 colkwargs = {'mjdCol': colmap['mjd'], 'seeingCol': colmap['seeingGeom'],
661 'expTimeCol': colmap['exptime'], 'm5Col': colmap['fiveSigmaDepth'],
662 'nightCol': colmap['night'], 'filterCol': colmap['filter']}
664 basicPlotDict = {'albedo': albedo, 'Hmark': Hmark, 'npReduce': npReduce,
665 'nxbins': 200, 'nybins': 200}
666 plotFuncs = [plots.MetricVsH()]
667 displayDict ={'group': 'Characterization'}
669 # Stackers
670 magStacker = stackers.MoMagStacker(lossCol='dmagDetect')
671 eclStacker = stackers.EclStacker()
672 stackerList = [magStacker, eclStacker]
674 # Windows are the different 'length of activity'
675 if windows is None:
676 windows = np.arange(10, 200, 30.)
677 # Bins are the different 'anomaly variations' of activity
678 if bins is None:
679 bins = np.arange(5, 185, 20.)
681 # Number of observations.
682 md = metadata
683 plotDict = {'ylabel': 'Number of observations (#)',
684 'title': '%s: Number of observations %s' % (runName, md)}
685 plotDict.update(basicPlotDict)
686 metric = metrics.NObsMetric(**colkwargs)
687 bundle = mb.MoMetricBundle(metric, slicer, constraint,
688 stackerList=stackerList,
689 runName=runName, metadata=md,
690 plotDict=plotDict, plotFuncs=plotFuncs,
691 displayDict=displayDict)
692 bundleList.append(bundle)
694 # Observational arc.
695 md = metadata
696 plotDict = {'ylabel': 'Observational Arc (days)',
697 'title': '%s: Observational Arc Length %s' % (runName, md)}
698 plotDict.update(basicPlotDict)
699 metric = metrics.ObsArcMetric(**colkwargs)
700 bundle = mb.MoMetricBundle(metric, slicer, constraint,
701 stackerList=stackerList,
702 runName=runName, metadata=md,
703 plotDict=plotDict, plotFuncs=plotFuncs,
704 displayDict=displayDict)
705 bundleList.append(bundle)
707 # Activity detection.
708 for w in windows:
709 md = metadata + ' activity lasting %.0f days' % w
710 plotDict = {'title': '%s: Chances of detecting %s' % (runName, md),
711 'ylabel': 'Probability of detection per %.0f day window' % w}
712 metricName = 'Chances of detecting activity lasting %.0f days' % w
713 metric = metrics.ActivityOverTimeMetric(w, metricName=metricName, **colkwargs)
714 bundle = mb.MoMetricBundle(metric, slicer, constraint,
715 stackerList=stackerList,
716 runName=runName, metadata=metadata,
717 plotDict=plotDict, plotFuncs=plotFuncs,
718 displayDict=displayDict)
719 bundleList.append(bundle)
721 for b in bins:
722 md = metadata + ' activity covering %.0f deg' % (b)
723 plotDict = {'title': '%s: Chances of detecting %s' % (runName, md),
724 'ylabel': 'Probability of detection per %.0f deg window' % b}
725 metricName = 'Chances of detecting activity covering %.0f deg' % (b)
726 metric = metrics.ActivityOverPeriodMetric(b, metricName=metricName, **colkwargs)
727 bundle = mb.MoMetricBundle(metric, slicer, constraint,
728 stackerList=stackerList,
729 runName=runName, metadata=metadata,
730 plotDict=plotDict, plotFuncs=plotFuncs,
731 displayDict=displayDict)
732 bundleList.append(bundle)
734 # Lightcurve inversion.
735 md = metadata
736 plotDict = {'yMin': 0, 'yMax': 1, 'ylabel': 'Fraction of objects',
737 'title': '%s: Fraction with potential lightcurve inversion %s' % (runName, md)}
738 plotDict.update(basicPlotDict)
739 metric = metrics.LightcurveInversion_AsteroidMetric(**colkwargs)
740 bundle = mb.MoMetricBundle(metric, slicer, constraint,
741 stackerList=stackerList,
742 runName=runName, metadata=md,
743 plotDict=plotDict, plotFuncs=plotFuncs,
744 displayDict=displayDict)
745 bundleList.append(bundle)
747 # Color determination.
748 md = metadata
749 plotDict = {'yMin': 0, 'yMax': 1, 'ylabel': 'Fraction of objects',
750 'title': '%s: Fraction of population with colors in X filters %s' % (runName, md)}
751 plotDict.update(basicPlotDict)
752 metric = metrics.Color_AsteroidMetric(**colkwargs)
753 bundle = mb.MoMetricBundle(metric, slicer, constraint,
754 stackerList=stackerList,
755 runName=runName, metadata=md,
756 plotDict=plotDict, plotFuncs=plotFuncs,
757 displayDict=displayDict)
758 bundleList.append(bundle)
760 # Set the runName for all bundles and return the bundleDict.
761 for b in bundleList:
762 b.setRunName(runName)
763 return mb.makeBundlesDictFromList(bundleList), plotBundles
766def characterizationOuterBatch(slicer, colmap=None, runName='opsim', metadata='',
767 albedo=None, Hmark=None, constraint=None, npReduce=np.mean,
768 windows=None, bins=None):
769 """Characterization metrics for outer solar system objects.
770 """
771 if colmap is None:
772 colmap = ColMapDict('opsimV4')
773 bundleList = []
774 plotBundles = []
776 # Set up a dictionary to pass to each metric for the column names.
777 colkwargs = {'mjdCol': colmap['mjd'], 'seeingCol': colmap['seeingGeom'],
778 'expTimeCol': colmap['exptime'], 'm5Col': colmap['fiveSigmaDepth'],
779 'nightCol': colmap['night'], 'filterCol': colmap['filter']}
781 basicPlotDict = {'albedo': albedo, 'Hmark': Hmark, 'npReduce': npReduce,
782 'nxbins': 200, 'nybins': 200}
783 plotFuncs = [plots.MetricVsH()]
784 displayDict ={'group': 'Characterization'}
786 # Stackers
787 magStacker = stackers.MoMagStacker(lossCol='dmagDetect')
788 eclStacker = stackers.EclStacker()
789 stackerList = [magStacker, eclStacker]
791 # Windows are the different 'length of activity'
792 if windows is None:
793 windows = np.arange(10, 200, 30.)
794 # Bins are the different 'anomaly variations' of activity
795 if bins is None:
796 bins = np.arange(5, 185, 20.)
798 # Number of observations.
799 md = metadata
800 plotDict = {'ylabel': 'Number of observations (#)',
801 'title': '%s: Number of observations %s' % (runName, md)}
802 plotDict.update(basicPlotDict)
803 metric = metrics.NObsMetric(**colkwargs)
804 bundle = mb.MoMetricBundle(metric, slicer, constraint,
805 stackerList=stackerList,
806 runName=runName, metadata=md,
807 plotDict=plotDict, plotFuncs=plotFuncs,
808 displayDict=displayDict)
809 bundleList.append(bundle)
811 # Observational arc.
812 md = metadata
813 plotDict = {'ylabel': 'Observational Arc (days)',
814 'title': '%s: Observational Arc Length %s' % (runName, md)}
815 plotDict.update(basicPlotDict)
816 metric = metrics.ObsArcMetric(**colkwargs)
817 bundle = mb.MoMetricBundle(metric, slicer, constraint,
818 stackerList=stackerList,
819 runName=runName, metadata=md,
820 plotDict=plotDict, plotFuncs=plotFuncs,
821 displayDict=displayDict)
822 bundleList.append(bundle)
824 # Activity detection.
825 for w in windows:
826 md = metadata + ' activity lasting %.0f days' % w
827 plotDict = {'title': '%s: Chances of detecting %s' % (runName, md),
828 'ylabel': 'Probability of detection per %.0f day window' % w}
829 metricName = 'Chances of detecting activity lasting %.0f days' % w
830 metric = metrics.ActivityOverTimeMetric(w, metricName=metricName, **colkwargs)
831 bundle = mb.MoMetricBundle(metric, slicer, constraint,
832 stackerList=stackerList,
833 runName=runName, metadata=metadata,
834 plotDict=plotDict, plotFuncs=plotFuncs,
835 displayDict=displayDict)
836 bundleList.append(bundle)
838 for b in bins:
839 md = metadata + ' activity covering %.0f deg' % (b)
840 plotDict = {'title': '%s: Chances of detecting %s' % (runName, md),
841 'ylabel': 'Probability of detection per %.2f deg window' % b}
842 metricName = 'Chances of detecting activity covering %.0f deg' % (b)
843 metric = metrics.ActivityOverPeriodMetric(b, metricName=metricName, **colkwargs)
844 bundle = mb.MoMetricBundle(metric, slicer, constraint,
845 stackerList=stackerList,
846 runName=runName, metadata=metadata,
847 plotDict=plotDict, plotFuncs=plotFuncs,
848 displayDict=displayDict)
849 bundleList.append(bundle)
851 # Color determination.
852 md = metadata
853 plotDict = {'yMin': 0, 'yMax': 1, 'ylabel': 'Fraction of objects',
854 'title': '%s: Fraction of population with colors in X filters %s' % (runName, md)}
855 plotDict.update(basicPlotDict)
856 metric = metrics.LightcurveColor_OuterMetric(**colkwargs)
857 bundle = mb.MoMetricBundle(metric, slicer, constraint,
858 stackerList=stackerList,
859 runName=runName, metadata=md,
860 plotDict=plotDict, plotFuncs=plotFuncs,
861 displayDict=displayDict)
862 bundleList.append(bundle)
864 # Set the runName for all bundles and return the bundleDict.
865 for b in bundleList:
866 b.setRunName(runName)
867 return mb.makeBundlesDictFromList(bundleList), plotBundles
870def runFractionSummary(bdict, Hmark, outDir, resultsDb):
871 """
872 Calculate fractional completeness of the population for color and lightcurve metrics.
874 This should be done after combining any sub-sets of the metric results.
876 Parameters
877 ----------
878 bdict : dict of metricBundles
879 Dict containing ~lsst.sims.maf.MoMetricBundles,
880 including bundles we're expecting to contain lightcurve/color evaluations.
881 Hmark : float
882 Hmark value to add to completeness plotting dict.
883 If defined, this value is used. If None, but Hmark in plotDict for metric, then this value (-2) is
884 used. If Hmark not in plotdict, then the median Hrange value - 2 is used.
885 times : np.ndarray
886 The times at which to calculate completeness (over time).
887 outDir : str
888 Output directory to save completeness bundles to disk.
889 resultsDb : ~lsst.sims.maf.db.ResultsDb
890 Results database to save information about completeness bundle.
892 Returns
893 -------
894 dict of metricBundles
895 Dictionary of the metric bundles for the fractional evaluation of the population.
896 """
897 fractions = {}
898 group = 'Characterization'
899 subgroup = 'Fraction of Population with Color/Lightcurve'
901 # Look for metrics from asteroid or outer solar system color/lightcurve metrics.
902 inversionSummary = fractionPopulationAtThreshold([1], ['Lightcurve Inversion'])
903 asteroidColorSummary = fractionPopulationAtThreshold([4, 3, 2, 1], ['6 of ugrizy', '5 of grizy',
904 '4 of grizy',
905 '2 of g, r or i, z or y'])
906 asteroidSummaryMetrics = {'LightcurveInversion_Asteroid': inversionSummary,
907 'Color_Asteroid': asteroidColorSummary}
909 outerColorSummary = fractionPopulationAtThreshold([6, 5, 4, 3, 2, 1], ['6 filters', '5 filters',
910 '4 filters', '3 filters',
911 '2 filters', '1 filters'])
912 outerSummaryMetrics = {'LightcurveColor_Outer': outerColorSummary}
914 for b, bundle in bdict.items():
915 # Find Hmark if not set (this may be different for different bundles).
916 if Hmark is None and 'Hmark' in bundle.plotDict:
917 Hmark = bundle.plotDict['Hmark'] - 2
918 if Hmark is None:
919 Hmark = np.median(bundle.slicer.slicePoints['H']) - 2
920 for k in asteroidSummaryMetrics:
921 if k in b:
922 for summary_metric in asteroidSummaryMetrics[k]:
923 newkey = b + ' ' + summary_metric.name
924 fractions[newkey] = mb.makeCompletenessBundle(bundle, summary_metric,
925 Hmark=Hmark, resultsDb=resultsDb)
926 for k in outerSummaryMetrics:
927 if k in b:
928 for summary_metric in outerSummaryMetrics[k]:
929 newkey = b + ' ' + summary_metric.name
930 fractions[newkey] = mb.makeCompletenessBundle(bundle, summary_metric,
931 Hmark=Hmark, resultsDb=resultsDb)
932 # Write the fractional populations bundles to disk, so we can re-read them later.
933 # (also set the display dict properties, for the resultsDb output).
934 for b, bundle in fractions.items():
935 bundle.setDisplayDict({'group': group, 'subgroup': subgroup})
936 bundle.write(outDir=outDir, resultsDb=resultsDb)
937 return fractions
940def plotFractions(bdictFractions, figroot=None, resultsDb=None,
941 outDir='.', figformat='pdf'):
942 # Set colors for the fractions.
943 for b in bdictFractions.values():
944 k = b.metric.name
945 print(k)
946 if '6' in k:
947 b.plotDict['color'] = 'b'
948 if '5' in k:
949 b.plotDict['color'] = 'cyan'
950 if '4' in k:
951 b.plotDict['color'] = 'orange'
952 if '2' in k:
953 b.plotDict['color'] = 'r'
954 if '1' in k:
955 b.plotDict['color'] = 'magenta'
956 if 'Lightcurve Inversion' in k:
957 b.plotDict['color'] = 'k'
958 b.plotDict['linestyle'] = ':'
959 b.plotDict['linewidth'] = 3
961 if figroot is None:
962 first = bdictFractions[list(bdictFractions.keys())[0]]
963 figroot = first.runName
965 displayDict = {'group': 'Characterization', 'subgroup': 'Color/Inversion'}
967 ph = plots.PlotHandler(figformat=figformat, resultsDb=resultsDb, outDir=outDir)
968 ph.setMetricBundles(bdictFractions)
969 ph.jointMetricNames = 'Fraction of population for colors or lightcurve inversion'
970 plotDict = {'ylabel': "Fraction of population", 'figsize': (8, 6)}
971 ph.plot(plotFunc=plots.MetricVsH(), plotDicts=plotDict, displayDict=displayDict,
972 outfileRoot=figroot + '_characterization')
975def plotSingle(bundle, resultsDb=None, outDir='.', figformat='pdf'):
976 """Plot 5%/25%/50%/75%/95% iles for a metric value.
977 """
978 pDict = {'95%ile': {'color': 'k', 'linestyle': '--', 'label': '95th %ile',
979 'npReduce': lambda x, axis: np.percentile(x, 95, axis=axis)},
980 '75%ile': {'color': 'magenta', 'linestyle': ':', 'label': '75th %ile',
981 'npReduce': lambda x, axis: np.percentile(x, 75, axis=axis)},
982 'Median': {'color': 'b', 'linestyle': '-', 'label': 'Median',
983 'npReduce': lambda x, axis: np.median(x, axis=axis)},
984 'Mean': {'color': 'g', 'linestyle': '--', 'label': 'Mean',
985 'npReduce': np.mean},
986 '25%ile': {'color': 'magenta', 'linestyle': ':', 'label': '25th %ile',
987 'npReduce': lambda x, axis: np.percentile(x, 25, axis=axis)},
988 '5%ile': {'color': 'k', 'linestyle': '--', 'label': '5th %ile',
989 'npReduce': lambda x, axis: np.percentile(x, 5, axis=axis)}}
990 displayDict = {'group': 'Characterization', 'subgroup': bundle.metric.name}
991 ph = plots.PlotHandler(figformat=figformat, resultsDb=resultsDb, outDir=outDir)
992 plotBundles = []
993 plotDicts = []
994 for r in pDict:
995 plotBundles.append(bundle)
996 plotDicts.append(pDict[r])
997 plotDicts[0].update({'figsize': (8, 6), 'legendloc': 'upper right', 'yMin': 0})
998 # Remove the Hmark line because these plots get complicated.
999 for r in plotDicts:
1000 del plotDicts[r]['Hmark']
1001 ph.setMetricBundles(plotBundles)
1002 ph.plot(plotFunc=plots.MetricVsH(), plotDicts=plotDicts, displayDict=displayDict)
1005def plotNotFound(nChances, Hmark):
1006 pass
1009def plotActivity(bdict, figroot=None, resultsDb=None, outDir='.', figformat='pdf'):
1010 activity_deg = {}
1011 activity_days = {}
1012 for k in bdict:
1013 if 'Chances_of_detecting_activity' in k:
1014 if 'deg' in k:
1015 activity_deg[k] = bdict[k]
1016 if 'days' in k:
1017 activity_days[k] = bdict[k]
1019 if figroot is None:
1020 first = bdict[list(bdict.keys())[0]]
1021 figroot = first.runName
1023 displayDict = {'group': 'Characterization', 'subgroup': 'Activity'}
1025 # Plot (mean) likelihood of detection of activity over X days
1026 ph = plots.PlotHandler(figformat=figformat, resultsDb=resultsDb, outDir=outDir)
1027 ph.setMetricBundles(activity_days)
1028 ph.jointMetricNames = 'Chances of detecting activity lasting X days'
1029 plotDict = {'ylabel': "Mean likelihood of detection", 'figsize': (8, 6)}
1030 ph.plot(plotFunc=plots.MetricVsH(), plotDicts=plotDict, displayDict=displayDict,
1031 outfileRoot=figroot + '_activityDays')
1032 # Plot (mean) likelihood of detection of activity over X amount of orbit
1033 ph.setMetricBundles(activity_deg)
1034 ph.jointMetricNames = 'Chances of detecting activity covering X deg'
1035 plotDict = {'ylabel': "Mean likelihood of detection", 'figsize': (8, 6)}
1036 ph.plot(plotFunc=plots.MetricVsH(), plotDicts=plotDict, displayDict=displayDict,
1037 outfileRoot=figroot + '_activityDeg')
1040def readAndCombine(orbitRoot, baseDir, splits, metricfile):
1041 """Read and combine the metric results from split locations, returning a single bundle.
1043 This will read the files from
1044 baseDir/orbitRoot_[split]/metricfile
1045 where split = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], etc. (the subsets the original orbit file was split into).
1047 Parameters
1048 ----------
1049 orbitRoot: str
1050 The root of the orbit file - l7_5k, mbas_5k, etc.
1051 baseDir: str
1052 The root directory containing the subset directories. (e.g. '.' often)
1053 splits: np.ndarray or list of ints
1054 The integers describing the split directories (e.g. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
1055 metricfile: str
1056 The metric filename.
1058 Returns
1059 -------
1060 ~lsst.sims.maf.bundle
1061 A single metric bundle containing the combined data from each of the subsets.
1063 Note that this won't work for particularly complex metric values, such as the parent Discovery metrics.
1064 However, you can read and combine their child metrics, as for these we can propagate the data masks.
1065 """
1066 subsets = {}
1067 for i in splits:
1068 subsets[i] = mb.createEmptyMoMetricBundle()
1069 ddir = os.path.join(baseDir, f'{orbitRoot}_{i}')
1070 subsets[i].read(os.path.join(ddir, metricfile))
1071 bundle = combineSubsets(subsets)
1072 return bundle
1075def combineSubsets(mbSubsets):
1076 # Combine the data from the subset metric bundles.
1077 # The first bundle will be used a template for the slicer.
1078 if isinstance(mbSubsets, dict):
1079 first = mbSubsets[list(mbSubsets.keys())[0]]
1080 else:
1081 first = mbSubsets[0]
1082 subsetdict = {}
1083 for i, b in enumerate(mbSubsets):
1084 subsetdict[i] = b
1085 mbSubsets = subsetdict
1086 joint = mb.createEmptyMoMetricBundle()
1087 # Check if they're the same slicer.
1088 slicer = deepcopy(first.slicer)
1089 for i in mbSubsets:
1090 if np.any(slicer.slicePoints['H'] != mbSubsets[i].slicer.slicePoints['H']):
1091 if np.any(slicer.slicePoints['orbits'] != mbSubsets[i].slicer.slicePoints['orbits']):
1092 raise ValueError('Bundle %s has a different slicer than the first bundle' % (i))
1093 # Join metric values.
1094 joint.slicer = slicer
1095 joint.metric = first.metric
1096 # Don't just use the slicer shape to define the metricValues, because of CompletenessBundles.
1097 metricValues = np.zeros(first.metricValues.shape, float)
1098 metricValuesMask = np.zeros(first.metricValues.shape, bool)
1099 for i in mbSubsets:
1100 metricValues += mbSubsets[i].metricValues.filled(0)
1101 metricValuesMask = np.where(metricValuesMask & mbSubsets[i].metricValues.mask, True, False)
1102 joint.metricValues = ma.MaskedArray(data=metricValues, mask=metricValuesMask, fill_value=0)
1103 joint.metadata = first.metadata
1104 joint.runName = first.runName
1105 joint.fileRoot = first.fileRoot.replace('.npz', '')
1106 joint.plotDict = first.plotDict
1107 return joint