Coverage for tests/test_finalizeCharacterization.py: 26%

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

89 statements  

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 

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

114 ('obj_index', 'i4')] 

115 

116 isolated_star_cat_dict = {} 

117 isolated_star_source_dict = {} 

118 

119 np.random.seed(12345) 

120 

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

122 nstar = 110 

123 nsource_per_band_per_star = 2 

124 self.nstar_total = nstar 

125 self.nstar_per_band = nstar - 10 

126 

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

128 for tract in [0, 1]: 

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

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

131 

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

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

134 cat['ra'] = ra 

135 cat['decl'] = dec 

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

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

138 

139 source_cats = [] 

140 counter = 0 

141 for i in range(cat.size): 

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

143 if i < 90: 

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

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

146 else: 

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

148 if i < 100: 

149 bands = ['i'] 

150 else: 

151 bands = ['r'] 

152 

153 for band in bands: 

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

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

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

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

158 tract*nstar + counter, 

159 tract*nstar + counter + nsource_per_band_per_star 

160 ) 

161 source_cat['obj_index'] = i 

162 

163 source_cats.append(source_cat) 

164 

165 counter += nsource_per_band_per_star 

166 

167 source_cat = np.concatenate(source_cats) 

168 

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

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

171 

172 return isolated_star_cat_dict, isolated_star_source_dict 

173 

174 def test_concat_isolated_star_cats(self): 

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

176 """ 

177 

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

179 iso, iso_src = self.finalizeCharacterizationTask.concat_isolated_star_cats( 

180 band, 

181 self.isolated_star_cat_dict, 

182 self.isolated_star_source_dict 

183 ) 

184 

185 # There are two tracts, so double everything. 

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

187 

188 reserve_fraction = self.finalizeCharacterizationTask.config.reserve_selection.reserve_fraction 

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

190 int(reserve_fraction*len(iso))) 

191 

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

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

194 

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

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

197 np.testing.assert_array_equal( 

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

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

200 i 

201 ) 

202 

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

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

205 for i in res_star: 

206 np.testing.assert_array_equal( 

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

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

209 True 

210 ) 

211 

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

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

214 np.testing.assert_array_equal( 

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

216 True 

217 ) 

218 

219 

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

221 pass 

222 

223 

224def setup_module(module): 

225 lsst.utils.tests.init() 

226 

227 

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

229 lsst.utils.tests.init() 

230 unittest.main()