Hide keyboard shortcuts

Hot-keys 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

1# This file is part of {{ cookiecutter.package_name }}. 

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 

22 

23import numpy as np 

24from astropy.io.votable.tree import Info 

25from astropy.io.votable import from_table 

26from astropy.table import Column 

27 

28import lsst.geom as geom 

29import lsst.afw.table as afwTable 

30 

31 

32def recordSelector(record, selection): 

33 """Select records from source catalog 

34 

35 Parameters: 

36 ----------- 

37 record : `lsst.afw.detect.SourceRecord` 

38 record to select 

39 selection : `str` 

40 'all' to select all records. 'blended parents' to select records with 

41 more than zero children. 'deblended children' to select records with 

42 non-zero parents. 'isolated' to select records that are not blended, 

43 meaning zero parents and zero children. 

44 Values to check for sel 

45 """ 

46 nChildren = record.get('deblend_nChild') 

47 parentId = record.getParent() 

48 if selection == 'all': 

49 return True 

50 elif selection == 'blended parents': 

51 return (nChildren > 0) 

52 elif selection == 'deblended children': 

53 return (parentId > 0) 

54 elif selection == 'isolated': 

55 return ((parentId == 0) and (nChildren == 0)) 

56 else: 

57 raise RuntimeError('invalid selection: {}'.format(selection) + 

58 '\nMust be one of "all", "blended parents", ' + 

59 '"deblended children", "isolated"') 

60 

61 

62def createFootprintsTable(catalog, xy0=None, insertColumn=4): 

63 """make a VOTable of SourceData table and footprints 

64 

65 Parameters: 

66 ----------- 

67 catalog : `lsst.afw.table.SourceCatalog` 

68 Source catalog from which to display footprints. 

69 xy0 : tuple or list or None 

70 Pixel origin to subtract off from the footprint coordinates. 

71 If None, the value used is (0,0) 

72 insertColumn : `int` 

73 Column at which to insert the "family_id" and "category" columns 

74 

75 Returns: 

76 -------- 

77 `astropy.io.votable.voTableFile` 

78 VOTable object to upload to Firefly 

79 """ 

80 if xy0 is None: 

81 xy0 = geom.Point2I(0, 0) 

82 

83 _catalog = afwTable.SourceCatalog(catalog.table.clone()) 

84 _catalog.extend(catalog, deep=True) 

85 sourceTable = _catalog.asAstropy() 

86 

87 # Change int64 dtypes so they convert to VOTable 

88 for colName in sourceTable.colnames: 

89 if sourceTable[colName].dtype.num == 9: 

90 sourceTable[colName].dtype = np.dtype('long') 

91 

92 inputColumnNames = sourceTable.colnames 

93 

94 x0, y0 = xy0 

95 spanList = [] 

96 peakList = [] 

97 familyList = [] 

98 categoryList = [] 

99 fpxll = [] 

100 fpyll = [] 

101 fpxur = [] 

102 fpyur = [] 

103 for record in catalog: 

104 footprint = record.getFootprint() 

105 recordId = record.getId() 

106 spans = footprint.getSpans() 

107 scoords = [(s.getY()-y0, s.getX0()-x0, s.getX1()-x0) for s in spans] 

108 scoords = np.array(scoords).flatten() 

109 scoords = np.ma.MaskedArray(scoords, mask=np.zeros(len(scoords), 

110 dtype=np.bool)) 

111 fpbbox = footprint.getBBox() 

112 corners = [(c.getX()-x0, c.getY()-y0) for c in fpbbox.getCorners()] 

113 fpxll.append(corners[0][0]) 

114 fpyll.append(corners[0][1]) 

115 fpxur.append(corners[2][0]) 

116 fpyur.append(corners[2][1]) 

117 peaks = footprint.getPeaks() 

118 pcoords = [(p.getFx()-x0, p.getFy()-y0) for p in peaks] 

119 pcoords = np.array(pcoords).flatten() 

120 pcoords = np.ma.MaskedArray(pcoords, mask=np.zeros(len(pcoords), 

121 dtype=np.bool)) 

122 fpbbox = footprint.getBBox() 

123 parentId = record.getParent() 

124 nChild = record.get('deblend_nChild') 

125 if parentId == 0: 

126 familyList.append(recordId) 

127 if nChild > 0: 

128 # blended parent 

129 categoryList.append('blended parent') 

130 else: 

131 # isolated 

132 categoryList.append('isolated') 

133 else: 

134 # deblended child 

135 familyList.append(parentId) 

136 categoryList.append('deblended child') 

137 spanList.append(scoords) 

138 peakList.append(pcoords) 

139 

140 sourceTable.add_column(Column(np.array(familyList)), 

141 name='family_id', 

142 index=insertColumn) 

143 sourceTable.add_column(Column(np.array(categoryList)), 

144 name='category', 

145 index=insertColumn+1) 

146 sourceTable.add_column(Column(np.array(spanList)), name='spans') 

147 sourceTable.add_column(Column(np.array(peakList)), name='peaks') 

148 sourceTable.add_column(Column(np.array(fpxll)), name='footprint_corner1_x') 

149 sourceTable.add_column(Column(np.array(fpyll)), name='footprint_corner1_y') 

150 sourceTable.add_column(Column(np.array(fpxur)), name='footprint_corner2_x') 

151 sourceTable.add_column(Column(np.array(fpyur)), name='footprint_corner2_y') 

152 

153 outputVO = from_table(sourceTable) 

154 outTable = outputVO.get_first_table() 

155 

156 outTable.infos.append(Info(name='contains_lsst_footprints', value='true')) 

157 outTable.infos.append(Info(name='contains_lsst_measurements', value='true')) 

158 outTable.infos.append(Info(name='FootPrintColumnNames', 

159 value='id;footprint_corner1_x;footprint_corner1_y;' + 

160 'footprint_corner2_x;footprint_corner2_y;spans;peaks')) 

161 outTable.infos.append(Info(name='pixelsys', value='zero-based')) 

162 # Check whether the coordinates are included and are valid 

163 if (('slot_Centroid_x' in inputColumnNames) and 

164 ('slot_Centroid_y' in inputColumnNames) and 

165 np.isfinite(outTable.array['slot_Centroid_x']).any() and 

166 np.isfinite(outTable.array['slot_Centroid_y']).any()): 

167 coord_column_string = 'slot_Centroid_x;slot_Centroid_y;ZERO_BASED' 

168 elif (('coord_ra' in inputColumnNames) and 

169 ('coord_dec' in inputColumnNames) and 

170 np.isfinite(outTable.array['coord_ra']).any() and 

171 np.isfinite(outTable.array['coord_dec']).any()): 

172 coord_column_string = 'coord_ra;coord_dec;EQ_J2000' 

173 elif (('base_SdssCentroid_x' in inputColumnNames) and 

174 ('base_SdssCentroid_y' in inputColumnNames) and 

175 np.isfinite(outTable.array['base_SdssCentroid_x']).any() and 

176 np.isfinite(outTable.array['base_SdssCentroid_y']).any()): 

177 coord_column_string = 'base_SdssCentroid_x;base_SdssCentroid_y;ZERO_BASED' 

178 elif (('base_NaiveCentroid_x' in inputColumnNames) and 

179 ('base_NaiveCentroid_y' in inputColumnNames) and 

180 np.isfinite(outTable.array['base_NaiveCentroid_x']).any() and 

181 np.isfinite(outTable.array['base_NaiveCentroid_y']).any()): 

182 coord_column_string = 'base_NaiveCentroid_x;base_NaiveCentroid_y;ZERO-BASED' 

183 else: 

184 raise RuntimeError('No valid coordinate columns in catalog') 

185 outTable.infos.append(Info(name='CatalogCoordColumns', 

186 value=coord_column_string)) 

187 

188 for f in outTable.fields: 

189 if f.datatype == 'bit': 

190 f.datatype = 'boolean' 

191 

192 outTable._config['version_1_3_or_later'] = True 

193 outputVO.set_all_tables_format('binary2') 

194 

195 return(outputVO)