Coverage for tests/test_finalizeCharacterization.py: 20%

97 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-11-03 01:34 -0700

1# This file is part of pipe_tasks. 

2# 

3# LSST Data Management System 

4# This product includes software developed by the 

5# LSST Project (http://www.lsst.org/). 

6# See COPYRIGHT file at the top of the source tree. 

7# 

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

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

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

11# (at your option) any later version. 

12# 

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

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

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

16# GNU General Public License for more details. 

17# 

18# You should have received a copy of the LSST License Statement and 

19# the GNU General Public License along with this program. If not, 

20# see <https://www.lsstcorp.org/LegalNotices/>. 

21# 

22"""Test FinalizeCharacterizationTask. 

23""" 

24import unittest 

25import numpy as np 

26import pandas as pd 

27 

28import lsst.utils.tests 

29import lsst.daf.butler 

30import lsst.pipe.base as pipeBase 

31 

32from lsst.pipe.tasks.finalizeCharacterization import (FinalizeCharacterizationConfig, 

33 FinalizeCharacterizationTask) 

34 

35 

36class MockDataFrameReference(lsst.daf.butler.DeferredDatasetHandle): 

37 """Very simple object that looks like a Gen3 data reference to 

38 a dataframe. 

39 """ 

40 def __init__(self, df): 

41 self.df = df 

42 

43 def get(self, parameters={}, **kwargs): 

44 """Retrieve the specified dataset using the API of the Gen3 Butler. 

45 

46 Parameters 

47 ---------- 

48 parameters : `dict`, optional 

49 Parameter dictionary. Supported key is ``columns``. 

50 

51 Returns 

52 ------- 

53 dataframe : `pandas.DataFrame` 

54 dataframe, cut to the specified columns. 

55 """ 

56 if 'columns' in parameters: 

57 _columns = parameters['columns'] 

58 

59 return self.df[_columns] 

60 else: 

61 return self.df.copy() 

62 

63 

64class TestFinalizeCharacterizationTask(FinalizeCharacterizationTask): 

65 """A derived class which skips the initialization routines. 

66 """ 

67 __test__ = False # Stop Pytest from trying to parse as a TestCase 

68 

69 def __init__(self, **kwargs): 

70 pipeBase.PipelineTask.__init__(self, **kwargs) 

71 

72 self.makeSubtask('reserve_selection') 

73 

74 

75class FinalizeCharacterizationTestCase(lsst.utils.tests.TestCase): 

76 """Tests of some functionality of FinalizeCharacterizationTask. 

77 

78 Full testing comes from integration tests such as ci_hsc and ci_imsim. 

79 

80 These tests bypass the middleware used for accessing data and 

81 managing Task execution. 

82 """ 

83 def setUp(self): 

84 config = FinalizeCharacterizationConfig() 

85 

86 self.finalizeCharacterizationTask = TestFinalizeCharacterizationTask( 

87 config=config, 

88 ) 

89 

90 self.isolated_star_cat_dict, self.isolated_star_source_dict = self._make_isocats() 

91 

92 def _make_isocats(self): 

93 """Make test isolated star catalogs. 

94 

95 Returns 

96 ------- 

97 isolated_star_cat_dict : `dict` 

98 Per-"tract" dict of isolated star catalogs. 

99 isolate_star_source_dict : `dict` 

100 Per-"tract" dict of isolated source catalogs. 

101 """ 

102 dtype_cat = [('isolated_star_id', 'i8'), 

103 ('ra', 'f8'), 

104 ('decl', 'f8'), 

105 ('primary_band', 'U2'), 

106 ('source_cat_index', 'i4'), 

107 ('nsource', 'i4'), 

108 ('source_cat_index_i', 'i4'), 

109 ('nsource_i', 'i4'), 

110 ('source_cat_index_r', 'i4'), 

111 ('nsource_r', 'i4'), 

112 ('source_cat_index_z', 'i4'), 

113 ('nsource_z', 'i4')] 

114 

115 dtype_source = [('sourceId', 'i8'), 

116 ('obj_index', 'i4')] 

117 

118 isolated_star_cat_dict = {} 

119 isolated_star_source_dict = {} 

120 

121 np.random.seed(12345) 

122 

123 # There are 90 stars in both r, i. 10 individually in each. 

124 nstar = 110 

125 nsource_per_band_per_star = 2 

126 self.nstar_total = nstar 

127 self.nstar_per_band = nstar - 10 

128 

129 # This is a brute-force assembly of a star catalog and matched sources. 

130 for tract in [0, 1, 2]: 

131 ra = np.random.uniform(low=tract, high=tract + 1.0, size=nstar) 

132 dec = np.random.uniform(low=0.0, high=1.0, size=nstar) 

133 

134 cat = np.zeros(nstar, dtype=dtype_cat) 

135 cat['isolated_star_id'] = tract*nstar + np.arange(nstar) 

136 cat['ra'] = ra 

137 cat['decl'] = dec 

138 if tract < 2: 

139 cat['primary_band'][0: 100] = 'i' 

140 cat['primary_band'][100:] = 'r' 

141 else: 

142 # Tract 2 only has z band. 

143 cat['primary_band'][:] = 'z' 

144 

145 source_cats = [] 

146 counter = 0 

147 for i in range(cat.size): 

148 cat['source_cat_index'][i] = counter 

149 if tract < 2: 

150 if i < 90: 

151 cat['nsource'][i] = 2*nsource_per_band_per_star 

152 bands = ['r', 'i'] 

153 else: 

154 cat['nsource'][i] = nsource_per_band_per_star 

155 if i < 100: 

156 bands = ['i'] 

157 else: 

158 bands = ['r'] 

159 else: 

160 cat['nsource'][i] = nsource_per_band_per_star 

161 bands = ['z'] 

162 

163 for band in bands: 

164 cat[f'source_cat_index_{band}'][i] = counter 

165 cat[f'nsource_{band}'][i] = nsource_per_band_per_star 

166 source_cat = np.zeros(nsource_per_band_per_star, dtype=dtype_source) 

167 source_cat['sourceId'] = np.arange( 

168 tract*nstar + counter, 

169 tract*nstar + counter + nsource_per_band_per_star 

170 ) 

171 source_cat['obj_index'] = i 

172 

173 source_cats.append(source_cat) 

174 

175 counter += nsource_per_band_per_star 

176 

177 source_cat = np.concatenate(source_cats) 

178 

179 isolated_star_cat_dict[tract] = MockDataFrameReference(pd.DataFrame(cat)) 

180 isolated_star_source_dict[tract] = MockDataFrameReference(pd.DataFrame(source_cat)) 

181 

182 return isolated_star_cat_dict, isolated_star_source_dict 

183 

184 def test_concat_isolated_star_cats(self): 

185 """Test concatenation and reservation of the isolated star catalogs. 

186 """ 

187 

188 for band in ['r', 'i']: 

189 iso, iso_src = self.finalizeCharacterizationTask.concat_isolated_star_cats( 

190 band, 

191 self.isolated_star_cat_dict, 

192 self.isolated_star_source_dict 

193 ) 

194 

195 # There are two tracts, so double everything. 

196 self.assertEqual(len(iso), 2*self.nstar_per_band) 

197 

198 reserve_fraction = self.finalizeCharacterizationTask.config.reserve_selection.reserve_fraction 

199 self.assertEqual(np.sum(iso['reserved']), 

200 int(reserve_fraction*len(iso))) 

201 

202 # 2 tracts, 4 observations per tract per star, minus 2*10 not in the given band. 

203 self.assertEqual(len(iso_src), 2*(4*len(iso)//2 - 20)) 

204 

205 # Check that every star is properly matched to the sources. 

206 for i in range(len(iso)): 

207 np.testing.assert_array_equal( 

208 iso_src['obj_index'][iso[f'source_cat_index_{band}'][i]: 

209 iso[f'source_cat_index_{band}'][i] + iso[f'nsource_{band}'][i]], 

210 i 

211 ) 

212 

213 # Check that every reserved star is marked as a reserved source. 

214 res_star, = np.where(iso['reserved']) 

215 for i in res_star: 

216 np.testing.assert_array_equal( 

217 iso_src['reserved'][iso[f'source_cat_index_{band}'][i]: 

218 iso[f'source_cat_index_{band}'][i] + iso[f'nsource_{band}'][i]], 

219 True 

220 ) 

221 

222 # Check that every reserved source is marked as a reserved star. 

223 res_src, = np.where(iso_src['reserved']) 

224 np.testing.assert_array_equal( 

225 iso['reserved'][iso_src['obj_index'][res_src]], 

226 True 

227 ) 

228 

229 def test_concat_isolate_star_cats_no_sources(self): 

230 """Test concatenation when there are no sources in a tract.""" 

231 iso, iso_src = self.finalizeCharacterizationTask.concat_isolated_star_cats( 

232 'z', 

233 self.isolated_star_cat_dict, 

234 self.isolated_star_source_dict 

235 ) 

236 

237 self.assertGreater(len(iso), 0) 

238 

239 

240class MyMemoryTestCase(lsst.utils.tests.MemoryTestCase): 

241 pass 

242 

243 

244def setup_module(module): 

245 lsst.utils.tests.init() 

246 

247 

248if __name__ == "__main__": 248 ↛ 249line 248 didn't jump to line 249, because the condition on line 248 was never true

249 lsst.utils.tests.init() 

250 unittest.main()