lsst.jointcal  master-gc935ebf72c
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Associations.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 #include <iostream>
4 #include <sstream>
5 
6 #include "lsst/log/Log.h"
12 #include "lsst/jointcal/Frame.h"
14 #include "lsst/jointcal/FatPoint.h"
15 #include "lsst/afw/image/Image.h"
16 #include "lsst/afw/image/VisitInfo.h"
17 #include "lsst/daf/base/PropertySet.h"
18 
19 #include "lsst/pex/exceptions.h"
20 #include "lsst/afw/geom/Box.h"
21 #include "lsst/afw/geom/Point.h"
22 #include "lsst/afw/coord/Coord.h"
23 #include "lsst/afw/image/Calib.h"
24 
25 namespace jointcal = lsst::jointcal;
26 
27 static double sqr(double x) { return x * x; }
28 
29 namespace {
30 LOG_LOGGER _log = LOG_GET("jointcal.Associations");
31 }
32 
33 namespace lsst {
34 namespace jointcal {
35 
37 
38 void Associations::addImage(lsst::afw::table::SortedCatalogT<lsst::afw::table::SourceRecord> &catalog,
39  std::shared_ptr<lsst::afw::image::TanWcs> wcs,
40  std::shared_ptr<lsst::afw::image::VisitInfo> visitInfo,
41  lsst::afw::geom::Box2I const &bbox, std::string const &filter,
42  std::shared_ptr<lsst::afw::image::Calib> calib, int visit, int ccd,
43  std::shared_ptr<lsst::jointcal::JointcalControl> control) {
44  auto ccdImage = std::make_shared<CcdImage>(catalog, wcs, visitInfo, bbox, filter, calib, visit, ccd,
45  control->sourceFluxField);
46  ccdImageList.push_back(ccdImage);
47  LOGLS_DEBUG(_log, "Catalog " << ccdImage->getName() << " has " << ccdImage->getWholeCatalog().size()
48  << " objects.");
49 }
50 
51 void Associations::setCommonTangentPoint(lsst::afw::geom::Point2D const &commonTangentPoint) {
52  _commonTangentPoint = Point(commonTangentPoint.getX(), commonTangentPoint.getY()); // a jointcal::Point
53  for (auto &ccdImage : ccdImageList) ccdImage->setCommonTangentPoint(_commonTangentPoint);
54 }
55 
56 void Associations::associateCatalogs(const double matchCutInArcSec, const bool useFittedList,
57  const bool enlargeFittedList) {
58  // clear reference stars
59  refStarList.clear();
60 
61  // clear measurement counts and associations to refstars, but keep fittedStars themselves.
62  for (auto &item : fittedStarList) {
63  item->clearBeforeAssoc();
64  }
65  // clear fitted stars
66  if (!useFittedList) fittedStarList.clear();
67 
68  for (auto &ccdImage : ccdImageList) {
69  const Gtransfo *toCommonTangentPlane = ccdImage->getPix2CommonTangentPlane();
70 
71  /* clear the catalog to fit and copy the whole catalog into it.
72  this allows reassociating from scratch after a fit. */
73 
74  ccdImage->getCatalogForFit().clear();
75  ccdImage->getWholeCatalog().copyTo(ccdImage->getCatalogForFit());
76  MeasuredStarList &catalog = ccdImage->getCatalogForFit();
77 
78  // associate with previous lists
79  /* to speed up the match (more precisely the contruction of the
80  FastFinder), select in the fittedStarList the objects that
81  are within reach of the current ccdImage
82  */
83  Frame ccdImageFrameCPT = applyTransfo(ccdImage->getImageFrame(), *toCommonTangentPlane, LargeFrame);
84  ccdImageFrameCPT = ccdImageFrameCPT.rescale(1.10); // add 10 % margin.
85  /* we cannot use FittedStarList::ExtractInFrame, because it does an
86  actual copy, which we don't want here: we want the pointers in
87  the StarMatch to refer to fittedStarList elements. */
88  FittedStarList toMatch;
89 
90  for (auto const &fittedStar : fittedStarList) {
91  if (ccdImageFrameCPT.inFrame(*fittedStar)) {
92  toMatch.push_back(fittedStar);
93  }
94  }
95 
96  // divide by 3600 because coordinates in CTP are in degrees.
97  auto starMatchList = listMatchCollect(Measured2Base(catalog), Fitted2Base(toMatch),
98  toCommonTangentPlane, matchCutInArcSec / 3600.);
99 
100  /* should check what this removeAmbiguities does... */
101  LOGLS_DEBUG(_log, "Measured-to-Fitted matches before removing ambiguities " << starMatchList->size());
102  starMatchList->removeAmbiguities(*toCommonTangentPlane);
103  LOGLS_DEBUG(_log, "Measured-to-Fitted matches after removing ambiguities " << starMatchList->size());
104 
105  /* associate MeasuredStar -> FittedStar using the
106  surviving matches */
107 
108  int matchedCount = 0;
109  for (auto const &starMatch : *starMatchList) {
110  auto bs = starMatch.s1;
111  auto ms_const = std::dynamic_pointer_cast<const MeasuredStar>(bs);
112  auto ms = std::const_pointer_cast<MeasuredStar>(ms_const);
113  auto bs2 = starMatch.s2;
114  auto fs_const = std::dynamic_pointer_cast<const FittedStar>(bs2);
115  auto fs = std::const_pointer_cast<FittedStar>(fs_const);
116  ms->setFittedStar(fs);
117  matchedCount++;
118  }
119  LOGLS_INFO(_log, "Matched " << matchedCount << " objects in " << ccdImage->getName());
120 
121  // add unmatched objets to FittedStarList
122  int unMatchedCount = 0;
123  for (auto const &mstar : catalog) {
124  // to check if it was matched, just check if it has a fittedStar Pointer assigned
125  if (mstar->getFittedStar()) continue;
126  if (enlargeFittedList) {
127  auto fs = std::make_shared<FittedStar>(*mstar);
128  // transform coordinates to CommonTangentPlane
129  toCommonTangentPlane->transformPosAndErrors(*fs, *fs);
130  fittedStarList.push_back(fs);
131  mstar->setFittedStar(fs);
132  }
133  unMatchedCount++;
134  }
135  LOGLS_INFO(_log, "Unmatched objects: " << unMatchedCount);
136  } // end of loop on CcdImages
137 
138  assignMags();
139 }
140 
141 void Associations::collectRefStars(lsst::afw::table::SortedCatalogT<lsst::afw::table::SimpleRecord> &refCat,
142  afw::geom::Angle matchCut, std::string const &fluxField) {
143  if (refCat.size() == 0) {
144  throw(LSST_EXCEPT(pex::exceptions::InvalidParameterError,
145  " reference catalog is empty : stop here "));
146  }
147 
148  // auto coordKey = refCat.getSchema().find<lsst::afw::coord::Coord>("coord").key;
149  // Same syntax as the following line but with auto : auto coordKey =
150  // afwTable::CoordKey(refCat.getSchema()["coord"]);
151  afw::table::CoordKey coordKey = refCat.getSchema()["coord"];
152  auto fluxKey = refCat.getSchema().find<double>(fluxField).key;
153 
154  for (auto const &record : refCat) {
155  lsst::afw::coord::Coord coord = record.get(coordKey);
156  double flux = record.get(fluxKey);
157  double mag = lsst::afw::image::abMagFromFlux(flux);
158  double ra = lsst::afw::geom::radToDeg(coord.getLongitude());
159  double dec = lsst::afw::geom::radToDeg(coord.getLatitude());
160  // TODO DM-10826: Why make a BaseStar here, when we're going to use it as a RefStar?
161  BaseStar star(ra, dec, mag);
162  // cook up errors: 100 mas per cooordinate
163 
164  // TODO DM-10826: What is this? Why are we making fake errors here?
165 
166  star.vx = sqr(0.1 / 3600 / cos(coord.getLatitude()));
167  star.vy = sqr(0.1 / 3600);
168  star.vxy = 0.;
169  refStarList.push_back(std::make_shared<RefStar>(star));
170  }
171 
172  // project on CTP (i.e. RaDec2CTP), in degrees
173  GtransfoLin identity;
174  TanRaDec2Pix raDec2CTP(identity, _commonTangentPoint);
175 
176  associateRefStars(matchCut.asArcseconds(), &raDec2CTP);
177 }
178 
179 const lsst::afw::geom::Box2D Associations::getRaDecBBox() {
180  // compute the frame on the CTP that contains all input images
181  Frame tangentPlaneFrame;
182 
183  for (auto const &ccdImage : ccdImageList) {
184  Frame CTPFrame =
185  applyTransfo(ccdImage->getImageFrame(), *(ccdImage->getPix2CommonTangentPlane()), LargeFrame);
186  if (tangentPlaneFrame.getArea() == 0)
187  tangentPlaneFrame = CTPFrame;
188  else
189  tangentPlaneFrame += CTPFrame;
190  }
191 
192  // convert tangent plane coordinates to RaDec:
193  GtransfoLin identity;
194  TanPix2RaDec CTP2RaDec(identity, _commonTangentPoint);
195  Frame raDecFrame = applyTransfo(tangentPlaneFrame, CTP2RaDec, LargeFrame);
196 
197  lsst::afw::geom::Point<double> min(raDecFrame.xMin, raDecFrame.yMin);
198  lsst::afw::geom::Point<double> max(raDecFrame.xMax, raDecFrame.yMax);
199  lsst::afw::geom::Box2D box(min, max);
200 
201  return box;
202 }
203 
204 void Associations::associateRefStars(double matchCutInArcSec, const Gtransfo *gtransfo) {
205  // associate with FittedStars
206  // 3600 because coordinates are in degrees (in CTP).
207  auto starMatchList = listMatchCollect(Ref2Base(refStarList), Fitted2Base(fittedStarList), gtransfo,
208  matchCutInArcSec / 3600.);
209 
210  LOGLS_DEBUG(_log, "Refcat matches before removing ambiguities " << starMatchList->size());
211  starMatchList->removeAmbiguities(*gtransfo);
212  LOGLS_DEBUG(_log, "Refcat matches after removing ambiguities " << starMatchList->size());
213 
214  // actually associate things
215  for (auto const &starMatch : *starMatchList) {
216  const BaseStar &bs = *starMatch.s1;
217  const RefStar &rs_const = dynamic_cast<const RefStar &>(bs);
218  RefStar &rs = const_cast<RefStar &>(rs_const);
219  const BaseStar &bs2 = *starMatch.s2;
220  const FittedStar &fs_const = dynamic_cast<const FittedStar &>(bs2);
221  FittedStar &fs = const_cast<FittedStar &>(fs_const);
222  // rs->setFittedStar(*fs);
223  fs.setRefStar(&rs);
224  }
225 
226  LOGLS_INFO(_log,
227  "Associated " << starMatchList->size() << " reference stars among " << refStarList.size());
228 }
229 
230 void Associations::selectFittedStars(int minMeasurements) {
231  LOGLS_INFO(_log, "Fitted stars before measurement # cut: " << fittedStarList.size());
232  /* first pass : remove objects that have less than a
233  certain number of measurements.
234  */
235  for (auto const &ccdImage : ccdImageList) {
236  MeasuredStarList &catalog = ccdImage->getCatalogForFit();
237  for (MeasuredStarIterator mi = catalog.begin(); mi != catalog.end();) {
238  MeasuredStar &mstar = **mi;
239 
240  auto fstar = mstar.getFittedStar();
241  if (!fstar) {
242  ++mi;
243  continue;
244  }
245 
246  /* keep FittedStar's which either have a minimum number of
247  measurements, or are matched to a RefStar
248  */
249  if (!fstar->getRefStar() && fstar->getMeasurementCount() < minMeasurements) {
250  auto f = std::const_pointer_cast<FittedStar>(fstar);
251  f->getMeasurementCount()--;
252  mi = catalog.erase(mi);
253  } else
254  ++mi;
255  } // end loop on objects in catalog
256  } // end loop on catalogs
257 
258  /* now FittedStars with less than minMeasurements should have
259  zero measurementCount; */
260 
261  for (FittedStarIterator fi = fittedStarList.begin(); fi != fittedStarList.end();) {
262  if ((*fi)->getMeasurementCount() == 0)
263  fi = fittedStarList.erase(fi);
264  else
265  ++fi;
266  }
267 
268  LOGLS_INFO(_log, "Fitted stars after measurement # cut: " << fittedStarList.size());
269 }
270 
271 void Associations::assignMags() {
272  for (auto const &ccdImage : ccdImageList) {
273  MeasuredStarList &catalog = ccdImage->getCatalogForFit();
274  for (auto const &mstar : catalog) {
275  auto fstar = mstar->getFittedStar();
276  if (!fstar) continue;
277  auto f = std::const_pointer_cast<FittedStar>(fstar);
278  f->addMagMeasurement(mstar->getMag(), mstar->getMagWeight());
279  }
280  }
281 }
282 
284  /* by default, Associations::fittedStarList is expressed on the
285  Associations::commonTangentPlane. For AstrometryFit, we need it on
286  the sky */
288  LOGLS_WARN(_log,
289  "DeprojectFittedStars: Fitted stars are already in sidereal coordinates, nothing done ");
290  return;
291  }
292 
294  fittedStarList.applyTransfo(ctp2Sky);
296 }
297 
298 #ifdef TODO
299 void Associations::collectMCStars(int realization) {
300  CcdImageIterator I;
301  StarMatchIterator smI;
302 
303  for (I = ccdImageList.begin(); I != ccdImageList.end(); I++) {
304  CcdImage &ccdImage = **I;
305  string dbimdir = ccdImage.Dir();
306  string mctruth = dbimdir + "/mc/mctruth.list";
307 
308  if (realization >= 0) {
309  stringstream sstrm;
310  sstrm << dbimdir << "/mc/mctruth_" << realization << ".list";
311  mctruth = sstrm.str();
312  }
313 
314  GtransfoIdentity gti;
315  MeasuredStarList &catalog = ccdImage.getCatalogForFit();
316 
317  // BaseStarWithErrorList mctruthlist(mctruth);
318  DicStarList mctruthlist(mctruth);
319  auto starMatchList =
320  listMatchCollect(Measured2Base(catalog), Dic2Base(mctruthlist), &gti, 1. /* pixel ? */);
321  if (starMatchList)
322  for (smI = starMatchList->begin(); smI != starMatchList->end(); smI++) {
323  StarMatch &sm = *smI;
324  BaseStar *bs = sm.s1;
325  MeasuredStar *mstar = dynamic_cast<MeasuredStar *>(bs);
326  bs = sm.s2;
327  DicStar *dstar = dynamic_cast<DicStar *>(bs);
328  std::unique_ptr<BaseStarWithError> mcstar(new BaseStarWithError(*bs));
329  mcstar->GetMCInfo().iflux = dstar->getval("iflux");
330  mcstar->GetMCInfo().tflux = dstar->getval("sflux");
331  /*
332  mstar->SetMCTruth(mcstar);
333  mstar->SetMCMeas(mcstar);
334  */
335  }
336  else
337  LOGLS_FATAL(_log, "CollectMCStars Unable to match MCTruth w/ catalog!");
338  }
339 }
340 
341 void Associations::setFittedStarColors(std::string dicStarListName, std::string color,
342  double matchCutArcSec) {
343  // decode color string in case it is x-y
344  size_t pos_minus = color.find('-');
345  bool compute_diff = (pos_minus != string::npos);
346  std::string c1, c2;
347  c1 = color.substr(0, pos_minus); // if pos_minus == npos, means "up to the end"
348  if (compute_diff) c2 = color.substr(pos_minus + 1, string::npos);
349  DicStarList cList(dicStarListName);
350  if (!cList.HasKey(c1))
351  throw(GastroException("Associations::SetFittedstarColors : " + dicStarListName +
352  " misses a key named \"" + c1 + "\""));
353  if (compute_diff && !cList.HasKey(c2))
354  throw(GastroException("Associations::SetFittedstarColors : " + dicStarListName +
355  " misses a key named \"" + c2 + "\""));
356  // we associate in some tangent plane. The reference catalog is expressed on the sky,
357  // but FittedStar's may be still in this tangent plane.
359  GtransfoIdentity id;
360  TanRaDec2Pix proj(GtransfoLin(), getCommonTangentPoint());
361  // project or not ?
362  Gtransfo *id_or_proj = &proj;
363  if (fittedStarList.inTangentPlaneCoordinates) id_or_proj = &id;
364  // The color List is to be projected:
365  TStarList projected_cList((BaseStarList &)cList, proj);
366  // Associate
367  auto starMatchList = listMatchCollect(Fitted2Base(fittedStarList), (const BaseStarList &)projected_cList,
368  id_or_proj, matchCutArcSec / 3600);
369 
370  LOGLS_INFO(_log, "Matched " << starMatchList->size() << '/' << fittedStarList.size()
371  << " FittedStars to color catalog");
372  // Evaluate and assign colors.
373  for (auto i = starMatchList->begin(); i != starMatchList->end(); ++i) {
374  BaseStar *s1 = i->s1;
375  FittedStar *fs = dynamic_cast<FittedStar *>(s1);
376  BaseStar *s2 = i->s2;
377  const TStar *ts = dynamic_cast<const TStar *>(s2);
378  const DicStar *ds = dynamic_cast<const DicStar *>(ts->get_original());
379  fs->color = ds->getval(c1);
380  if (compute_diff) fs->color -= ds->getval(c2);
381  }
382 }
383 
384 #endif /* STORAGE */
385 } // namespace jointcal
386 } // namespace lsst
Point getCommonTangentPoint() const
can be used to project sidereal coordinates related to the image set on a plane.
Definition: Associations.h:56
Objects used as position anchors, typically USNO stars.
Definition: RefStar.h:16
implements the linear transformations (6 real coefficients).
Definition: Gtransfo.h:288
MeasuredStarList::iterator MeasuredStarIterator
Definition: MeasuredStar.h:79
A point in a plane.
Definition: Point.h:13
the transformation that handles pix to sideral transfos (Gnomonic, possibly with polynomial distortio...
Definition: Gtransfo.h:439
StarList< BaseStar > BaseStarList
Definition: BaseStar.h:81
void addMagMeasurement(double magValue, double magWeight)
this routine will hopefully soon disappear.
Definition: FittedStar.cc:45
void addImage(lsst::afw::table::SortedCatalogT< lsst::afw::table::SourceRecord > &catalog, std::shared_ptr< lsst::afw::image::TanWcs > wcs, std::shared_ptr< lsst::afw::image::VisitInfo > visitInfo, lsst::afw::geom::Box2I const &bbox, std::string const &filter, std::shared_ptr< lsst::afw::image::Calib > calib, int visit, int ccd, std::shared_ptr< lsst::jointcal::JointcalControl > control)
Create a ccdImage from an exposure catalog and metadata, and add it to the list.
Definition: Associations.cc:38
std::shared_ptr< const FittedStar > getFittedStar() const
Definition: MeasuredStar.h:56
double xMin
coordinate of boundary.
Definition: Frame.h:22
void associateCatalogs(const double matchCutInArcsec=0, const bool useFittedList=false, const bool enlargeFittedList=true)
incrementaly builds a merged catalog of all image catalogs
Definition: Associations.cc:56
A list of MeasuredStar. They are usually filled in Associations::AddImage.
Definition: MeasuredStar.h:71
void selectFittedStars(int minMeasurements)
Set the color field of FittedStar &#39;s from a colored catalog.
pairs of points
The base class for handling stars. Used by all matching routines.
Definition: BaseStar.h:26
rectangle with sides parallel to axes.
Definition: Frame.h:19
void setRefStar(const RefStar *_refStar)
Set the astrometric reference star associated with this star.
Definition: FittedStar.cc:34
FittedStarList::iterator FittedStarIterator
Definition: FittedStar.h:143
virtual void transformPosAndErrors(const FatPoint &in, FatPoint &out) const
Definition: Gtransfo.cc:99
A list of FittedStar s. Such a list is typically constructed by Associations.
Definition: FittedStar.h:134
std::unique_ptr< StarMatchList > listMatchCollect(const BaseStarList &list1, const BaseStarList &list2, const Gtransfo *guess, const double maxDist)
assembles star matches.
Definition: ListMatch.cc:540
objects measured on actual images.
Definition: MeasuredStar.h:18
::std::list< StarMatch >::iterator StarMatchIterator
Definition: StarMatch.h:111
void deprojectFittedStars()
Sends back the fitted stars coordinates on the sky FittedStarsList::inTangentPlaneCoordinates keeps t...
const MeasuredStarList & getCatalogForFit() const
Gets the catalog to be used for fitting, which may have been cleaned-up.
Definition: CcdImage.h:93
void setCommonTangentPoint(lsst::afw::geom::Point2D const &commonTangentPoint)
Sets a shared tangent point for all ccdImages.
Definition: Associations.cc:51
This one is the Tangent Plane (called gnomonic) projection (from celestial sphere to tangent plane) ...
Definition: Gtransfo.h:513
Combinatorial searches for linear transformations to go from list1 to list2.
double getArea() const
Definition: Frame.cc:102
BaseStarList & Fitted2Base(FittedStarList &This)
Definition: FittedStar.cc:52
a virtual (interface) class for geometric transformations.
Definition: Gtransfo.h:37
const lsst::afw::geom::Box2D getRaDecBBox()
BaseStarList & Measured2Base(MeasuredStarList &This)
Definition: MeasuredStar.cc:35
int getMeasurementCount() const
Definition: FittedStar.h:98
Associations()
Source selection is performed in python, so Associations&#39; constructor only initializes a couple of va...
Definition: Associations.cc:36
void collectRefStars(lsst::afw::table::SortedCatalogT< lsst::afw::table::SimpleRecord > &refCat, afw::geom::Angle matchCut, std::string const &fluxField)
Collect stars from an external reference catalog and associate them with fittedStars.
Frame rescale(const double factor) const
rescale it. The center does not move.
Definition: Frame.cc:94
Frame applyTransfo(const Frame &inputframe, const Gtransfo &gtransfo, const WhichTransformed which)
Transform a Frame through a Transfo.
Definition: AstroUtils.cc:15
Handler of an actual image from a single CCD.
Definition: CcdImage.h:31
void applyTransfo(const Operator &op)
enables to apply a geometrical transfo if Star is Basestar or derives from it.
Definition: StarList.h:75
The objects which have been measured several times.
Definition: FittedStar.h:34
FittedStarList fittedStarList
Definition: Associations.h:32
BaseStarList & Ref2Base(RefStarList &This)
Definition: RefStar.cc:23