LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
footprints.py
Go to the documentation of this file.
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 -----------
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)
def createFootprintsTable(catalog, xy0=None, insertColumn=4)
Definition: footprints.py:62
def recordSelector(record, selection)
Definition: footprints.py:32
bool any(CoordinateExpr< N > const &expr) noexcept
Return true if any elements are true.
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174