LSSTApplications  19.0.0-14-gb0260a2+72efe9b372,20.0.0+7927753e06,20.0.0+8829bf0056,20.0.0+995114c5d2,20.0.0+b6f4b2abd1,20.0.0+bddc4f4cbe,20.0.0-1-g253301a+8829bf0056,20.0.0-1-g2b7511a+0d71a2d77f,20.0.0-1-g5b95a8c+7461dd0434,20.0.0-12-g321c96ea+23efe4bbff,20.0.0-16-gfab17e72e+fdf35455f6,20.0.0-2-g0070d88+ba3ffc8f0b,20.0.0-2-g4dae9ad+ee58a624b3,20.0.0-2-g61b8584+5d3db074ba,20.0.0-2-gb780d76+d529cf1a41,20.0.0-2-ged6426c+226a441f5f,20.0.0-2-gf072044+8829bf0056,20.0.0-2-gf1f7952+ee58a624b3,20.0.0-20-geae50cf+e37fec0aee,20.0.0-25-g3dcad98+544a109665,20.0.0-25-g5eafb0f+ee58a624b3,20.0.0-27-g64178ef+f1f297b00a,20.0.0-3-g4cc78c6+e0676b0dc8,20.0.0-3-g8f21e14+4fd2c12c9a,20.0.0-3-gbd60e8c+187b78b4b8,20.0.0-3-gbecbe05+48431fa087,20.0.0-38-ge4adf513+a12e1f8e37,20.0.0-4-g97dc21a+544a109665,20.0.0-4-gb4befbc+087873070b,20.0.0-4-gf910f65+5d3db074ba,20.0.0-5-gdfe0fee+199202a608,20.0.0-5-gfbfe500+d529cf1a41,20.0.0-6-g64f541c+d529cf1a41,20.0.0-6-g9a5b7a1+a1cd37312e,20.0.0-68-ga3f3dda+5fca18c6a4,20.0.0-9-g4aef684+e18322736b,w.2020.45
LSSTDataManagementBasePackage
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 
23 import numpy as np
24 from astropy.io.votable.tree import Info
25 from astropy.io.votable import from_table
26 from astropy.table import Column
27 
28 import lsst.geom as geom
29 import lsst.afw.table as afwTable
30 
31 
32 def 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 
62 def 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)
lsst.display.firefly.footprints.createFootprintsTable
def createFootprintsTable(catalog, xy0=None, insertColumn=4)
Definition: footprints.py:62
lsst.pex.config.history.format
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
lsst::afw::table._source.SourceCatalog
Definition: _source.py:32
lsst::geom::any
bool any(CoordinateExpr< N > const &expr) noexcept
Return true if any elements are true.
Definition: CoordinateExpr.h:89
lsst::afw::table
Definition: table.dox:3
lsst::geom
Definition: AffineTransform.h:36
lsst.display.firefly.footprints.recordSelector
def recordSelector(record, selection)
Definition: footprints.py:32
lsst::geom::Point< int, 2 >