Coverage for python/lsst/faro/base/CatalogMeasurementBase.py: 48%

Shortcuts 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

49 statements  

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/>. 

21from astropy.table import Table, hstack 

22import astropy.units as u 

23 

24import lsst.pipe.base as pipeBase 

25import lsst.pex.config as pexConfig 

26from lsst.verify.tasks import MetricTask, MetricConfig, MetricConnections 

27from lsst.pipe.tasks.loadReferenceCatalog import LoadReferenceCatalogTask 

28import lsst.geom 

29 

30from .BaseSubTasks import NumSourcesTask 

31 

32__all__ = ( 

33 "CatalogMeasurementBaseConnections", 

34 "CatalogMeasurementBaseConfig", 

35 "CatalogMeasurementBaseTask", 

36) 

37 

38 

39class CatalogMeasurementBaseConnections( 

40 MetricConnections, defaultTemplates={"refDataset": ""} 

41): 

42 

43 refCat = pipeBase.connectionTypes.PrerequisiteInput( 

44 doc="Reference catalog", 

45 name="{refDataset}", 

46 storageClass="SimpleCatalog", 

47 dimensions=("skypix",), 

48 deferLoad=True, 

49 multiple=True, 

50 ) 

51 

52 def __init__(self, *, config=None): 

53 super().__init__(config=config) 

54 if config.connections.refDataset == "": 

55 self.prerequisiteInputs.remove("refCat") 

56 

57 

58class CatalogMeasurementBaseConfig( 

59 MetricConfig, pipelineConnections=CatalogMeasurementBaseConnections 

60): 

61 """Configuration for CatalogMeasurementBaseTask.""" 

62 

63 measure = pexConfig.ConfigurableField( 

64 # This task is meant to make measurements of various types. 

65 # The default task is, therefore, a bit of a place holder. 

66 # It is expected that this will be overridden in the pipeline 

67 # definition in most cases. 

68 target=NumSourcesTask, 

69 doc="Measure task", 

70 ) 

71 

72 referenceCatalogLoader = pexConfig.ConfigurableField( 

73 target=LoadReferenceCatalogTask, doc="Reference catalog loader", 

74 ) 

75 

76 def setDefaults(self): 

77 self.referenceCatalogLoader.refObjLoader.ref_dataset_name = "" 

78 self.referenceCatalogLoader.doApplyColorTerms = False 

79 

80 def validate(self): 

81 super().validate() 

82 if ( 

83 self.connections.refDataset 

84 != self.referenceCatalogLoader.refObjLoader.ref_dataset_name 

85 ): 

86 msg = "The reference datasets specified in connections and reference catalog loader must match." 

87 raise pexConfig.FieldValidationError( 

88 CatalogMeasurementBaseConfig.referenceCatalogLoader, self, msg 

89 ) 

90 

91 

92class CatalogMeasurementBaseTask(MetricTask): 

93 """Base class for science performance metrics measured from source/object catalogs.""" 

94 

95 ConfigClass = CatalogMeasurementBaseConfig 

96 _DefaultName = "catalogMeasurementBaseTask" 

97 

98 def __init__(self, config, *args, **kwargs): 

99 super().__init__(*args, config=config, **kwargs) 

100 self.makeSubtask("measure") 

101 

102 def run(self, **kwargs): 

103 return self.measure.run(self.config.connections.metric, **kwargs) 

104 

105 def _getReferenceCatalog(self, butlerQC, dataIds, refCats, filterList, epoch=None): 

106 """Load reference catalog in sky region of interest and optionally applies proper 

107 motion correction and color terms. 

108 

109 Loads the `lsst.afw.table.SimpleCatalog` reference catalog, computes ra and dec 

110 (optionally) applying a proper motion correction. Also, color terms 

111 are (optionally) applied to the reference magnitudes in order to transform 

112 them to the data's photometric system. 

113 

114 returns a refCat with both the original loaded reference catalog and 

115 the coorected coordinates (ra,dec) and transformed reference magnitudes 

116 (refMag-/refMagErr-) 

117 

118 Parameters 

119 ---------- 

120 butlerQC : `lsst.pipe.base.butlerQuantumContext.ButlerQuantumContext` 

121 Butler quantum context for a Gen3 repository. 

122 dataIds: interable of `lsst.daf.butler.dataId` 

123 An iterable object of dataIds that point to reference catalogs 

124 in a Gen3 repository. 

125 refCats : iterable of `lsst.daf.butler.DeferredDatasetHandle` 

126 An iterable object of dataset refs for reference catalogs in 

127 a Gen3 repository. 

128 filterList : `list` [`str`] 

129 List of camera physicalFilter names to apply color terms. 

130 epoch : `astropy.time.Time`, optional 

131 Epoch to which to correct proper motion and parallax 

132 (if available), or `None` to not apply such corrections. 

133 

134 Returns 

135 ------- 

136 refCat: pandas.dataframe 

137 a reference catalog with original columns and corrected 

138 coordinates (ra,dec) and reference magnitudes (refMag-/refMagErr-) 

139 """ 

140 center = lsst.geom.SpherePoint( 

141 butlerQC.quantum.dataId.region.getBoundingCircle().getCenter() 

142 ) 

143 radius = butlerQC.quantum.dataId.region.getBoundingCircle().getOpeningAngle() 

144 

145 loaderTask = LoadReferenceCatalogTask( 

146 config=self.config.referenceCatalogLoader, dataIds=dataIds, refCats=refCats 

147 ) 

148 

149 # Get catalog with proper motion and color terms applied 

150 refCatCorrected = loaderTask.getSkyCircleCatalog( 

151 center, radius, filterList, epoch=epoch 

152 ) 

153 

154 # Get unformatted catalog w/ all columns 

155 skyCircle = loaderTask.refObjLoader.loadSkyCircle( 

156 center, radius, loaderTask._referenceFilter, epoch=epoch 

157 ) 

158 refCat = skyCircle.refCat 

159 

160 refCatTable = Table() 

161 refCatTable['ra'] = refCatCorrected['ra']*u.deg 

162 refCatTable['dec'] = refCatCorrected['ra']*u.deg 

163 for n, filterName in enumerate(filterList): 

164 refCatTable['refMag-' + filterName] = refCatCorrected["refMag"][:, n]*u.ABmag 

165 refCatTable['refMagErr-' + filterName] = refCatCorrected["refMagErr"][:, n]*u.ABmag 

166 refCatFrame = hstack([refCatTable, refCat.asAstropy()]).to_pandas() 

167 

168 return refCatFrame