Coverage for tests/test_finalizeCharacterization.py: 18%

88 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-13 11:43 +0000

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.pipe.base as pipeBase 

30 

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

32 FinalizeCharacterizationTask) 

33 

34 

35class TestFinalizeCharacterizationTask(FinalizeCharacterizationTask): 

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

37 """ 

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

39 

40 def __init__(self, **kwargs): 

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

42 

43 self.makeSubtask('reserve_selection') 

44 

45 

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

47 """Tests of some functionality of FinalizeCharacterizationTask. 

48 

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

50 

51 These tests bypass the middleware used for accessing data and 

52 managing Task execution. 

53 """ 

54 def setUp(self): 

55 config = FinalizeCharacterizationConfig() 

56 

57 self.finalizeCharacterizationTask = TestFinalizeCharacterizationTask( 

58 config=config, 

59 ) 

60 

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

62 

63 def _make_isocats(self): 

64 """Make test isolated star catalogs. 

65 

66 Returns 

67 ------- 

68 isolated_star_cat_dict : `dict` 

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

70 isolate_star_source_dict : `dict` 

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

72 """ 

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

74 ('ra', 'f8'), 

75 ('dec', 'f8'), 

76 ('primary_band', 'U2'), 

77 ('source_cat_index', 'i4'), 

78 ('nsource', 'i4'), 

79 ('source_cat_index_i', 'i4'), 

80 ('nsource_i', 'i4'), 

81 ('source_cat_index_r', 'i4'), 

82 ('nsource_r', 'i4'), 

83 ('source_cat_index_z', 'i4'), 

84 ('nsource_z', 'i4')] 

85 

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

87 ('obj_index', 'i4')] 

88 

89 isolated_star_cat_dict = {} 

90 isolated_star_source_dict = {} 

91 

92 np.random.seed(12345) 

93 

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

95 nstar = 110 

96 nsource_per_band_per_star = 2 

97 self.nstar_total = nstar 

98 self.nstar_per_band = nstar - 10 

99 

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

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

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

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

104 

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

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

107 cat['ra'] = ra 

108 cat['dec'] = dec 

109 if tract < 2: 

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

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

112 else: 

113 # Tract 2 only has z band. 

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

115 

116 source_cats = [] 

117 counter = 0 

118 for i in range(cat.size): 

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

120 if tract < 2: 

121 if i < 90: 

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

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

124 else: 

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

126 if i < 100: 

127 bands = ['i'] 

128 else: 

129 bands = ['r'] 

130 else: 

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

132 bands = ['z'] 

133 

134 for band in bands: 

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

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

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

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

139 tract*nstar + counter, 

140 tract*nstar + counter + nsource_per_band_per_star 

141 ) 

142 source_cat['obj_index'] = i 

143 

144 source_cats.append(source_cat) 

145 

146 counter += nsource_per_band_per_star 

147 

148 source_cat = np.concatenate(source_cats) 

149 

150 isolated_star_cat_dict[tract] = pipeBase.InMemoryDatasetHandle(pd.DataFrame(cat), 

151 storageClass="DataFrame") 

152 isolated_star_source_dict[tract] = pipeBase.InMemoryDatasetHandle(pd.DataFrame(source_cat), 

153 storageClass="DataFrame") 

154 

155 return isolated_star_cat_dict, isolated_star_source_dict 

156 

157 def test_concat_isolated_star_cats(self): 

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

159 """ 

160 

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

162 iso, iso_src = self.finalizeCharacterizationTask.concat_isolated_star_cats( 

163 band, 

164 self.isolated_star_cat_dict, 

165 self.isolated_star_source_dict 

166 ) 

167 

168 # There are two tracts, so double everything. 

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

170 

171 reserve_fraction = self.finalizeCharacterizationTask.config.reserve_selection.reserve_fraction 

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

173 int(reserve_fraction*len(iso))) 

174 

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

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

177 

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

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

180 np.testing.assert_array_equal( 

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

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

183 i 

184 ) 

185 

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

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

188 for i in res_star: 

189 np.testing.assert_array_equal( 

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

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

192 True 

193 ) 

194 

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

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

197 np.testing.assert_array_equal( 

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

199 True 

200 ) 

201 

202 def test_concat_isolate_star_cats_no_sources(self): 

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

204 iso, iso_src = self.finalizeCharacterizationTask.concat_isolated_star_cats( 

205 'z', 

206 self.isolated_star_cat_dict, 

207 self.isolated_star_source_dict 

208 ) 

209 

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

211 

212 

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

214 pass 

215 

216 

217def setup_module(module): 

218 lsst.utils.tests.init() 

219 

220 

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

222 lsst.utils.tests.init() 

223 unittest.main()