LSSTApplications  16.0-11-g09ed895+2,16.0-11-g12e47bd,16.0-11-g9bb73b2+6,16.0-12-g5c924a4+6,16.0-14-g9a974b3+1,16.0-15-g1417920+1,16.0-15-gdd5ca33+1,16.0-16-gf0259e2,16.0-17-g31abd91+7,16.0-17-g7d7456e+7,16.0-17-ga3d2e9f+13,16.0-18-ga4d4bcb+1,16.0-18-gd06566c+1,16.0-2-g0febb12+21,16.0-2-g9d5294e+69,16.0-2-ga8830df+6,16.0-20-g21842373+7,16.0-24-g3eae5ec,16.0-28-gfc9ea6c+4,16.0-29-ge8801f9,16.0-3-ge00e371+34,16.0-4-g18f3627+13,16.0-4-g5f3a788+20,16.0-4-ga3eb747+10,16.0-4-gabf74b7+29,16.0-4-gb13d127+6,16.0-49-g42e581f7+6,16.0-5-g27fb78a+7,16.0-5-g6a53317+34,16.0-5-gb3f8a4b+87,16.0-6-g9321be7+4,16.0-6-gcbc7b31+42,16.0-6-gf49912c+29,16.0-7-gd2eeba5+51,16.0-71-ge89f8615e,16.0-8-g21fd5fe+29,16.0-8-g3a9f023+20,16.0-8-g4734f7a+1,16.0-8-g5858431+3,16.0-9-gf5c1f43+8,master-gd73dc1d098+1,w.2019.01
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.afw.geom as afwGeom
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 = afwGeom.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 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:129
def createFootprintsTable(catalog, xy0=None, insertColumn=4)
Definition: footprints.py:62