Hide keyboard shortcuts

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

1# This file is part of faro. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with this program. If not, see <https://www.gnu.org/licenses/>. 

21 

22import astropy.units as u 

23import numpy as np 

24from lsst.pipe.base import Struct, Task 

25from lsst.pex.config import Config, Field 

26from lsst.verify import Measurement 

27 

28from lsst.faro.utils.matcher import mergeCatalogs 

29 

30__all__ = ( 

31 "NumSourcesTask", 

32 "NumSourcesMergeTask", 

33 "NumpySummaryConfig", 

34 "NumpySummaryTask", 

35) 

36 

37 

38class NumSourcesConfig(Config): 

39 doPrimary = Field( 

40 doc="Only count sources where detect_isPrimary is True.", 

41 dtype=bool, 

42 default=False, 

43 ) 

44 

45 

46class NumSourcesTask(Task): 

47 r"""Simple default task count the number of sources/objects in catalog.""" 

48 

49 ConfigClass = NumSourcesConfig 

50 _DefaultName = "numSourcesTask" 

51 

52 def run(self, metricName, catalog, **kwargs): 

53 """Run NumSourcesTask 

54 

55 Parameters 

56 ---------- 

57 metricName : `str` 

58 The name of the metric to measure. 

59 catalog : `dict` 

60 `lsst.afw.table` Catalog type 

61 kwargs 

62 Extra keyword arguments used to construct the task. 

63 

64 Returns 

65 ------- 

66 measurement : `Struct` 

67 The measured value of the metric. 

68 """ 

69 self.log.info("Measuring %s", metricName) 

70 if self.config.doPrimary: 

71 nSources = np.sum(catalog["detect_isPrimary"] is True) 

72 else: 

73 nSources = len(catalog) 

74 self.log.info("Number of sources (nSources) = %i" % nSources) 

75 meas = Measurement("nsrcMeas", nSources * u.count) 

76 return Struct(measurement=meas) 

77 

78 

79class NumSourcesMergeTask(Task): 

80 

81 ConfigClass = Config 

82 _DefaultName = "numSourcesMergeTask" 

83 

84 def run(self, metricName, catalogs, photoCalibs, astromCalibs, **kwargs): 

85 self.log.info("Measuring %s", metricName) 

86 catalog = mergeCatalogs(catalogs, photoCalibs, astromCalibs) 

87 nSources = len(catalog) 

88 meas = Measurement("nsrcMeas", nSources * u.count) 

89 return Struct(measurement=meas) 

90 

91 

92class NumpySummaryConfig(Config): 

93 summary = Field( 

94 dtype=str, default="median", doc="Aggregation to use for summary metrics" 

95 ) 

96 

97 

98class NumpySummaryTask(Task): 

99 

100 ConfigClass = NumpySummaryConfig 

101 _DefaultName = "numpySummaryTask" 

102 

103 def run(self, measurements, agg_name, package, metric): 

104 agg = agg_name.lower() 

105 if agg == "summary": 

106 agg = self.config.summary 

107 self.log.info("Computing the %s of %s_%s values", agg, package, metric) 

108 

109 if len(measurements) == 0: 

110 self.log.info("Received zero length measurements list. Returning NaN.") 

111 # In the case of an empty list, there is nothing we can do other than 

112 # to return a NaN 

113 value = u.Quantity(np.nan) 

114 else: 

115 unit = measurements[0].quantity.unit 

116 value = getattr(np, agg)( 

117 u.Quantity( 

118 [x.quantity for x in measurements if np.isfinite(x.quantity)] 

119 ) 

120 ) 

121 # Make sure return has same unit as inputs 

122 # In some cases numpy can return a NaN and the unit gets dropped 

123 value = value.value * unit 

124 return Struct( 

125 measurement=Measurement( 

126 f"metricvalue_{agg_name.lower()}_{package}_{metric}", value 

127 ) 

128 )