Coverage for python/lsst/meas/astrom/match_probabilistic_task.py: 27%

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

58 statements  

1# This file is part of meas_astrom. 

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 lsst.afw.geom as afwGeom 

23import lsst.geom as geom 

24import lsst.pipe.base as pipeBase 

25import lsst.utils as utils 

26from .matcher_probabilistic import MatchProbabilisticConfig, MatcherProbabilistic 

27 

28import logging 

29import numpy as np 

30import pandas as pd 

31from typing import Dict, Set, Tuple 

32 

33__all__ = ['MatchProbabilisticTask'] 

34 

35 

36class MatchProbabilisticTask(pipeBase.Task): 

37 """Run MatchProbabilistic on a reference and target catalog covering the same tract. 

38 """ 

39 ConfigClass = MatchProbabilisticConfig 

40 _DefaultName = "matchProbabilistic" 

41 

42 @property 

43 def columns_in_ref(self) -> Set[str]: 

44 return self.config.columns_in_ref() 

45 

46 @property 

47 def columns_in_target(self) -> Set[str]: 

48 return self.config.columns_in_target() 

49 

50 def match( 

51 self, 

52 catalog_ref: pd.DataFrame, 

53 catalog_target: pd.DataFrame, 

54 select_ref: np.array = None, 

55 select_target: np.array = None, 

56 wcs: afwGeom.SkyWcs = None, 

57 logger: logging.Logger = None, 

58 logging_n_rows: int = None, 

59 ) -> Tuple[pd.DataFrame, pd.DataFrame, Dict[int, str]]: 

60 """Match sources in a reference tract catalog with a target catalog. 

61 

62 Parameters 

63 ---------- 

64 catalog_ref : `pandas.DataFrame` 

65 A reference catalog to match objects/sources from. 

66 catalog_target : `pandas.DataFrame` 

67 A target catalog to match reference objects/sources to. 

68 select_ref : `numpy.array` 

69 A boolean array of the same length as `catalog_ref` selecting the sources that can be matched. 

70 select_target : `numpy.array` 

71 A boolean array of the same length as `catalog_target` selecting the sources that can be matched. 

72 wcs : `lsst.afw.image.SkyWcs` 

73 A coordinate system to convert catalog positions to sky coordinates. Only used if 

74 `self.config.coords_ref_to_convert` is set. 

75 logger : `logging.Logger` 

76 A Logger for logging. 

77 logging_n_rows : `int` 

78 Number of matches to make before outputting incremental log message. 

79 

80 Returns 

81 ------- 

82 catalog_out_ref : `pandas.DataFrame` 

83 Reference matched catalog with indices of target matches. 

84 catalog_out_target : `pandas.DataFrame` 

85 Reference matched catalog with indices of target matches. 

86 """ 

87 if logger is None: 

88 logger = self.log 

89 

90 config = self.config 

91 

92 if config.column_order is None: 

93 flux_tot = np.nansum(catalog_ref.loc[:, config.columns_ref_flux].values, axis=1) 

94 catalog_ref['flux_total'] = flux_tot 

95 if config.mag_brightest_ref != -np.inf or config.mag_faintest_ref != np.inf: 

96 mag_tot = -2.5 * np.log10(flux_tot) + config.mag_zeropoint_ref 

97 select_mag = (mag_tot >= config.mag_brightest_ref) & ( 

98 mag_tot <= config.mag_faintest_ref) 

99 else: 

100 select_mag = np.isfinite(flux_tot) 

101 if select_ref is None: 

102 select_ref = select_mag 

103 else: 

104 select_ref &= select_mag 

105 

106 if config.coords_ref_to_convert: 

107 ra_ref, dec_ref = [catalog_ref[column] for column in config.coords_ref_to_convert.keys()] 

108 factor = config.coords_ref_factor 

109 radec_true = [geom.SpherePoint(ra*factor, dec*factor, geom.degrees) 

110 for ra, dec in zip(ra_ref, dec_ref)] 

111 xy_true = wcs.skyToPixel(radec_true) 

112 

113 for idx_coord, column_out in enumerate(config.coords_ref_to_convert.values()): 

114 catalog_ref[column_out] = np.array([xy[idx_coord] for xy in xy_true]) 

115 

116 select_additional = (len(config.columns_target_select_true) 

117 + len(config.columns_target_select_false)) > 0 

118 if select_additional: 

119 if select_target is None: 

120 select_target = np.ones(len(catalog_target), dtype=bool) 

121 for column in config.columns_target_select_true: 

122 select_target &= catalog_target[column].values 

123 for column in config.columns_target_select_false: 

124 select_target &= ~catalog_target[column].values 

125 

126 logger.info('Beginning MatcherProbabilistic.match with %d/%d ref sources selected vs %d/%d target', 

127 np.sum(select_ref), len(select_ref), np.sum(select_target), len(select_target)) 

128 

129 catalog_out_ref, catalog_out_target, exceptions = self.matcher.match( 

130 catalog_ref, 

131 catalog_target, 

132 select_ref=select_ref, 

133 select_target=select_target, 

134 logger=logger, 

135 logging_n_rows=logging_n_rows, 

136 ) 

137 

138 return catalog_out_ref, catalog_out_target, exceptions 

139 

140 @utils.timer.timeMethod 

141 def run( 

142 self, 

143 catalog_ref: pd.DataFrame, 

144 catalog_target: pd.DataFrame, 

145 wcs: afwGeom.SkyWcs = None, 

146 **kwargs, 

147 ) -> pipeBase.Struct: 

148 """Match sources in a reference tract catalog with a target catalog. 

149 

150 Parameters 

151 ---------- 

152 catalog_ref : `pandas.DataFrame` 

153 A reference catalog to match objects/sources from. 

154 catalog_target : `pandas.DataFrame` 

155 A target catalog to match reference objects/sources to. 

156 wcs : `lsst.afw.image.SkyWcs` 

157 A coordinate system to convert catalog positions to sky coordinates. 

158 Only needed if `config.coords_ref_to_convert` is used to convert 

159 reference catalog sky coordinates to pixel positions. 

160 kwargs : Additional keyword arguments to pass to `match`. 

161 

162 Returns 

163 ------- 

164 retStruct : `lsst.pipe.base.Struct` 

165 A struct with output_ref and output_target attribute containing the 

166 output matched catalogs, as well as a dict 

167 """ 

168 catalog_ref, catalog_target, exceptions = self.match(catalog_ref, catalog_target, wcs=wcs, **kwargs) 

169 return pipeBase.Struct(cat_output_ref=catalog_ref, cat_output_target=catalog_target, 

170 exceptions=exceptions) 

171 

172 def __init__(self, **kwargs): 

173 super().__init__(**kwargs) 

174 self.matcher = MatcherProbabilistic(self.config)