13 from lsst.verify
import Job, Measurement
18 from .dataIds
import PerTractCcdDataIdContainer
23 __all__ = [
"JointcalConfig",
"JointcalRunner",
"JointcalTask"]
25 Photometry = collections.namedtuple(
'Photometry', (
'fit',
'model'))
26 Astrometry = collections.namedtuple(
'Astrometry', (
'fit',
'model',
'sky_to_tan_projection'))
31 meas = Measurement(job.metrics[name], value)
32 job.measurements.insert(meas)
36 """Subclass of TaskRunner for jointcalTask 38 jointcalTask.runDataRef() takes a number of arguments, one of which is a list of dataRefs 39 extracted from the command line (whereas most CmdLineTasks' runDataRef methods take 40 single dataRef, are are called repeatedly). This class transforms the processed 41 arguments generated by the ArgumentParser into the arguments expected by 42 Jointcal.runDataRef(). 44 See pipeBase.TaskRunner for more information. 50 Return a list of tuples per tract, each containing (dataRefs, kwargs). 52 Jointcal operates on lists of dataRefs simultaneously. 54 kwargs[
'profile_jointcal'] = parsedCmd.profile_jointcal
55 kwargs[
'butler'] = parsedCmd.butler
59 for ref
in parsedCmd.id.refList:
60 refListDict.setdefault(ref.dataId[
"tract"], []).append(ref)
62 result = [(refListDict[tract], kwargs)
for tract
in sorted(refListDict.keys())]
70 Arguments for Task.runDataRef() 75 if self.doReturnResults is False: 77 - ``exitStatus``: 0 if the task completed successfully, 1 otherwise. 79 if self.doReturnResults is True: 81 - ``result``: the result of calling jointcal.runDataRef() 82 - ``exitStatus``: 0 if the task completed successfully, 1 otherwise. 87 dataRefList, kwargs = args
88 butler = kwargs.pop(
'butler')
89 task = self.TaskClass(config=self.config, log=self.log, butler=butler)
92 result = task.runDataRef(dataRefList, **kwargs)
93 exitStatus = result.exitStatus
94 job_path = butler.get(
'verify_job_filename')
95 result.job.write(job_path[0])
96 except Exception
as e:
101 eName = type(e).__name__
102 tract = dataRefList[0].dataId[
'tract']
103 task.log.fatal(
"Failed processing tract %s, %s: %s", tract, eName, e)
105 if self.doReturnResults:
106 return pipeBase.Struct(result=result, exitStatus=exitStatus)
108 return pipeBase.Struct(exitStatus=exitStatus)
112 """Config for JointcalTask""" 114 doAstrometry = pexConfig.Field(
115 doc=
"Fit astrometry and write the fitted result.",
119 doPhotometry = pexConfig.Field(
120 doc=
"Fit photometry and write the fitted result.",
124 coaddName = pexConfig.Field(
125 doc=
"Type of coadd, typically deep or goodSeeing",
129 posError = pexConfig.Field(
130 doc=
"Constant term for error on position (in pixel unit)",
135 matchCut = pexConfig.Field(
136 doc=
"Matching radius between fitted and reference stars (arcseconds)",
140 minMeasurements = pexConfig.Field(
141 doc=
"Minimum number of associated measured stars for a fitted star to be included in the fit",
145 minMeasuredStarsPerCcd = pexConfig.Field(
146 doc=
"Minimum number of measuredStars per ccdImage before printing warnings",
150 minRefStarsPerCcd = pexConfig.Field(
151 doc=
"Minimum number of measuredStars per ccdImage before printing warnings",
155 allowLineSearch = pexConfig.Field(
156 doc=
"Allow a line search during minimization, if it is reasonable for the model" 157 " (models with a significant non-linear component, e.g. constrainedPhotometry).",
161 astrometrySimpleOrder = pexConfig.Field(
162 doc=
"Polynomial order for fitting the simple astrometry model.",
166 astrometryChipOrder = pexConfig.Field(
167 doc=
"Order of the per-chip transform for the constrained astrometry model.",
171 astrometryVisitOrder = pexConfig.Field(
172 doc=
"Order of the per-visit transform for the constrained astrometry model.",
176 useInputWcs = pexConfig.Field(
177 doc=
"Use the input calexp WCSs to initialize a SimpleAstrometryModel.",
181 astrometryModel = pexConfig.ChoiceField(
182 doc=
"Type of model to fit to astrometry",
184 default=
"constrained",
185 allowed={
"simple":
"One polynomial per ccd",
186 "constrained":
"One polynomial per ccd, and one polynomial per visit"}
188 photometryModel = pexConfig.ChoiceField(
189 doc=
"Type of model to fit to photometry",
191 default=
"constrainedMagnitude",
192 allowed={
"simpleFlux":
"One constant zeropoint per ccd and visit, fitting in flux space.",
193 "constrainedFlux":
"Constrained zeropoint per ccd, and one polynomial per visit," 194 " fitting in flux space.",
195 "simpleMagnitude":
"One constant zeropoint per ccd and visit," 196 " fitting in magnitude space.",
197 "constrainedMagnitude":
"Constrained zeropoint per ccd, and one polynomial per visit," 198 " fitting in magnitude space.",
201 photometryVisitOrder = pexConfig.Field(
202 doc=
"Order of the per-visit polynomial transform for the constrained photometry model.",
206 photometryDoRankUpdate = pexConfig.Field(
207 doc=
"Do the rank update step during minimization. " 208 "Skipping this can help deal with models that are too non-linear.",
212 astrometryDoRankUpdate = pexConfig.Field(
213 doc=
"Do the rank update step during minimization (should not change the astrometry fit). " 214 "Skipping this can help deal with models that are too non-linear.",
218 outlierRejectSigma = pexConfig.Field(
219 doc=
"How many sigma to reject outliers at during minimization.",
223 maxPhotometrySteps = pexConfig.Field(
224 doc=
"Maximum number of minimize iterations to take when fitting photometry.",
228 maxAstrometrySteps = pexConfig.Field(
229 doc=
"Maximum number of minimize iterations to take when fitting photometry.",
233 astrometryRefObjLoader = pexConfig.ConfigurableField(
234 target=LoadIndexedReferenceObjectsTask,
235 doc=
"Reference object loader for astrometric fit",
237 photometryRefObjLoader = pexConfig.ConfigurableField(
238 target=LoadIndexedReferenceObjectsTask,
239 doc=
"Reference object loader for photometric fit",
241 sourceSelector = sourceSelectorRegistry.makeField(
242 doc=
"How to select sources for cross-matching",
245 writeInitMatrix = pexConfig.Field(
247 doc=
"Write the pre/post-initialization Hessian and gradient to text files, for debugging." 248 "The output files will be of the form 'astrometry_preinit-mat.txt', in the current directory." 249 "Note that these files are the dense versions of the matrix, and so may be very large.",
252 writeChi2ContributionFiles = pexConfig.Field(
254 doc=
"Write initial/final fit files containing the contributions to chi2.",
257 sourceFluxType = pexConfig.Field(
259 doc=
"Source flux field to use in source selection and to get fluxes from the catalog.",
265 sourceSelector.setDefaults()
267 sourceSelector.badFlags.extend([
"slot_Shape_flag"])
273 """Jointly astrometrically and photometrically calibrate a group of images.""" 275 ConfigClass = JointcalConfig
276 RunnerClass = JointcalRunner
277 _DefaultName =
"jointcal" 279 def __init__(self, butler=None, profile_jointcal=False, **kwargs):
281 Instantiate a JointcalTask. 285 butler : lsst.daf.persistence.Butler 286 The butler is passed to the refObjLoader constructor in case it is 287 needed. Ignored if the refObjLoader argument provides a loader directly. 288 Used to initialize the astrometry and photometry refObjLoaders. 289 profile_jointcal : bool 290 set to True to profile different stages of this jointcal run. 292 pipeBase.CmdLineTask.__init__(self, **kwargs)
294 self.makeSubtask(
"sourceSelector")
295 if self.config.doAstrometry:
296 self.makeSubtask(
'astrometryRefObjLoader', butler=butler)
297 if self.config.doPhotometry:
298 self.makeSubtask(
'photometryRefObjLoader', butler=butler)
301 self.
job = Job.load_metrics_package(subset=
'jointcal')
305 def _getConfigName(self):
308 def _getMetadataName(self):
312 def _makeArgumentParser(cls):
313 """Create an argument parser""" 315 parser.add_argument(
"--profile_jointcal", default=
False, action=
"store_true",
316 help=
"Profile steps of jointcal separately.")
317 parser.add_id_argument(
"--id",
"calexp", help=
"data ID, e.g. --id visit=6789 ccd=0..9",
318 ContainerClass=PerTractCcdDataIdContainer)
321 def _build_ccdImage(self, dataRef, associations, jointcalControl):
323 Extract the necessary things from this dataRef to add a new ccdImage. 327 dataRef : lsst.daf.persistence.ButlerDataRef 328 dataRef to extract info from. 329 associations : lsst.jointcal.Associations 330 object to add the info to, to construct a new CcdImage 331 jointcalControl : jointcal.JointcalControl 332 control object for associations management 337 wcs : lsst.afw.geom.SkyWcs 338 the TAN WCS of this image, read from the calexp 340 a key to identify this dataRef by its visit and ccd ids 344 if "visit" in dataRef.dataId.keys():
345 visit = dataRef.dataId[
"visit"]
347 visit = dataRef.getButler().queryMetadata(
"calexp", (
"visit"), dataRef.dataId)[0]
349 src = dataRef.get(
"src", flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS, immediate=
True)
351 visitInfo = dataRef.get(
'calexp_visitInfo')
352 detector = dataRef.get(
'calexp_detector')
353 ccdId = detector.getId()
354 calib = dataRef.get(
'calexp_calib')
355 tanWcs = dataRef.get(
'calexp_wcs')
356 bbox = dataRef.get(
'calexp_bbox')
357 filt = dataRef.get(
'calexp_filter')
358 filterName = filt.getName()
359 fluxMag0 = calib.getFluxMag0()
360 photoCalib = afwImage.PhotoCalib(1.0/fluxMag0[0], fluxMag0[1]/fluxMag0[0]**2, bbox)
362 goodSrc = self.sourceSelector.run(src)
364 if len(goodSrc.sourceCat) == 0:
365 self.log.warn(
"No sources selected in visit %s ccd %s", visit, ccdId)
367 self.log.info(
"%d sources selected in visit %d ccd %d", len(goodSrc.sourceCat), visit, ccdId)
368 associations.createCcdImage(goodSrc.sourceCat,
379 Result = collections.namedtuple(
'Result_from_build_CcdImage', (
'wcs',
'key',
'filter'))
380 Key = collections.namedtuple(
'Key', (
'visit',
'ccd'))
381 return Result(tanWcs, Key(visit, ccdId), filterName)
386 Jointly calibrate the astrometry and photometry across a set of images. 390 dataRefs : list of lsst.daf.persistence.ButlerDataRef 391 List of data references to the exposures to be fit. 392 profile_jointcal : bool 393 Profile the individual steps of jointcal. 399 * dataRefs: the provided data references that were fit (with updated WCSs) 400 * oldWcsList: the original WCS from each dataRef 401 * metrics: dictionary of internally-computed metrics for testing/validation. 403 if len(dataRefs) == 0:
404 raise ValueError(
'Need a non-empty list of data references!')
408 sourceFluxField =
"slot_%sFlux" % (self.config.sourceFluxType,)
412 visit_ccd_to_dataRef = {}
415 load_cat_prof_file =
'jointcal_build_ccdImage.prof' if profile_jointcal
else '' 416 with pipeBase.cmdLineTask.profile(load_cat_prof_file):
419 camera = dataRefs[0].get(
'camera', immediate=
True)
423 oldWcsList.append(result.wcs)
424 visit_ccd_to_dataRef[result.key] = ref
425 filters.append(result.filter)
426 filters = collections.Counter(filters)
428 associations.computeCommonTangentPoint()
433 bbox = associations.getRaDecBBox()
435 bboxCenter = bbox.getCenter()
436 center = afwGeom.SpherePoint(bboxCenter[0], bboxCenter[1], afwGeom.degrees)
437 bboxMax = bbox.getMax()
438 corner = afwGeom.SpherePoint(bboxMax[0], bboxMax[1], afwGeom.degrees)
439 radius = center.separation(corner).asRadians()
444 raise RuntimeError(
"astrometry_net_data is not setup")
447 defaultFilter = filters.most_common(1)[0][0]
448 self.log.debug(
"Using %s band for reference flux", defaultFilter)
451 tract = dataRefs[0].dataId[
'tract']
453 if self.config.doAstrometry:
456 refObjLoader=self.astrometryRefObjLoader,
458 profile_jointcal=profile_jointcal,
464 if self.config.doPhotometry:
467 refObjLoader=self.photometryRefObjLoader,
469 profile_jointcal=profile_jointcal,
472 reject_bad_fluxes=
True)
477 return pipeBase.Struct(dataRefs=dataRefs,
478 oldWcsList=oldWcsList,
480 exitStatus=exitStatus)
482 def _do_load_refcat_and_fit(self, associations, defaultFilter, center, radius,
483 name="", refObjLoader=None, filters=[], fit_function=None,
484 tract=None, profile_jointcal=False, match_cut=3.0,
485 reject_bad_fluxes=False):
486 """Load reference catalog, perform the fit, and return the result. 490 associations : lsst.jointcal.Associations 491 The star/reference star associations to fit. 493 filter to load from reference catalog. 494 center : lsst.afw.geom.SpherePoint 495 ICRS center of field to load from reference catalog. 496 radius : lsst.afw.geom.Angle 497 On-sky radius to load from reference catalog. 499 Name of thing being fit: "Astrometry" or "Photometry". 500 refObjLoader : lsst.meas.algorithms.LoadReferenceObjectsTask 501 Reference object loader to load from for fit. 502 filters : list of str, optional 503 List of filters to load from the reference catalog. 504 fit_function : function 505 function to call to perform fit (takes associations object). 507 Name of tract currently being fit. 508 profile_jointcal : bool, optional 509 Separately profile the fitting step. 510 match_cut : float, optional 511 Radius in arcseconds to find cross-catalog matches to during 512 associations.associateCatalogs. 513 reject_bad_fluxes : bool, optional 514 Reject refCat sources with NaN/inf flux or NaN/0 fluxErr. 518 Result of `fit_function()` 520 self.log.info(
"====== Now processing %s...", name)
523 associations.associateCatalogs(match_cut)
525 associations.fittedStarListSize())
527 skyCircle = refObjLoader.loadSkyCircle(center,
528 afwGeom.Angle(radius, afwGeom.radians),
532 if not skyCircle.refCat.isContiguous():
533 refCat = skyCircle.refCat.copy(deep=
True)
535 refCat = skyCircle.refCat
542 filtKeys = lsst.meas.algorithms.getRefFluxKeys(refCat.schema, filt)
543 refFluxes[filt] = refCat.get(filtKeys[0])
544 refFluxErrs[filt] = refCat.get(filtKeys[1])
546 associations.collectRefStars(refCat, self.config.matchCut*afwGeom.arcseconds,
547 skyCircle.fluxField, refFluxes, refFluxErrs, reject_bad_fluxes)
549 associations.refStarListSize())
551 associations.prepareFittedStars(self.config.minMeasurements)
555 associations.nFittedStarsWithAssociatedRefStar())
557 associations.fittedStarListSize())
559 associations.nCcdImagesValidForFit())
561 load_cat_prof_file =
'jointcal_fit_%s.prof'%name
if profile_jointcal
else '' 562 dataName =
"{}_{}".format(tract, defaultFilter)
563 with pipeBase.cmdLineTask.profile(load_cat_prof_file):
564 result = fit_function(associations, dataName)
567 if self.config.writeChi2ContributionFiles:
568 baseName =
"{}_final_chi2-{}.csv".format(name, dataName)
569 result.fit.saveChi2Contributions(baseName)
573 def _check_star_lists(self, associations, name):
575 if associations.nCcdImagesValidForFit() == 0:
576 raise RuntimeError(
'No images in the ccdImageList!')
577 if associations.fittedStarListSize() == 0:
578 raise RuntimeError(
'No stars in the {} fittedStarList!'.format(name))
579 if associations.refStarListSize() == 0:
580 raise RuntimeError(
'No stars in the {} reference star list!'.format(name))
582 def _fit_photometry(self, associations, dataName=None):
584 Fit the photometric data. 588 associations : lsst.jointcal.Associations 589 The star/reference star associations to fit. 591 Name of the data being processed (e.g. "1234_HSC-Y"), for 592 identifying debugging files. 597 fit : lsst.jointcal.PhotometryFit 598 The photometric fitter used to perform the fit. 599 model : lsst.jointcal.PhotometryModel 600 The photometric model that was fit. 602 self.log.info(
"=== Starting photometric fitting...")
605 if self.config.photometryModel ==
"constrainedFlux":
608 visitOrder=self.config.photometryVisitOrder)
610 doLineSearch = self.config.allowLineSearch
611 elif self.config.photometryModel ==
"constrainedMagnitude":
614 visitOrder=self.config.photometryVisitOrder)
616 doLineSearch = self.config.allowLineSearch
617 elif self.config.photometryModel ==
"simpleFlux":
620 elif self.config.photometryModel ==
"simpleMagnitude":
625 chi2 = fit.computeChi2()
628 if self.config.writeChi2ContributionFiles:
629 baseName =
"photometry_initial_chi2-{}.csv".format(dataName)
630 fit.saveChi2Contributions(baseName)
632 if not np.isfinite(chi2.chi2):
633 raise FloatingPointError(
'Initial chi2 is invalid: %s'%chi2)
634 self.log.info(
"Initialized: %s", str(chi2))
637 dumpMatrixFile =
"photometry_preinit" if self.config.writeInitMatrix
else "" 638 if self.config.photometryModel.startswith(
"constrained"):
641 fit.minimize(
"ModelVisit", dumpMatrixFile=dumpMatrixFile)
642 chi2 = fit.computeChi2()
643 self.log.info(str(chi2))
645 fit.minimize(
"Model", doLineSearch=doLineSearch, dumpMatrixFile=dumpMatrixFile)
646 chi2 = fit.computeChi2()
647 self.log.info(str(chi2))
648 fit.minimize(
"Fluxes")
649 chi2 = fit.computeChi2()
650 self.log.info(str(chi2))
651 fit.minimize(
"Model Fluxes", doLineSearch=doLineSearch)
652 chi2 = fit.computeChi2()
653 if not np.isfinite(chi2.chi2):
654 raise FloatingPointError(
'Pre-iteration chi2 is invalid: %s'%chi2)
655 self.log.info(
"Fit prepared with %s", str(chi2))
657 model.freezeErrorTransform()
658 self.log.debug(
"Photometry error scales are frozen.")
662 self.config.maxPhotometrySteps,
665 doRankUpdate=self.config.photometryDoRankUpdate,
666 doLineSearch=doLineSearch,
673 def _fit_astrometry(self, associations, dataName=None):
675 Fit the astrometric data. 679 associations : lsst.jointcal.Associations 680 The star/reference star associations to fit. 682 Name of the data being processed (e.g. "1234_HSC-Y"), for 683 identifying debugging files. 688 fit : lsst.jointcal.AstrometryFit 689 The astrometric fitter used to perform the fit. 690 model : lsst.jointcal.AstrometryModel 691 The astrometric model that was fit. 692 sky_to_tan_projection : lsst.jointcal.ProjectionHandler 693 The model for the sky to tangent plane projection that was used in the fit. 696 self.log.info(
"=== Starting astrometric fitting...")
698 associations.deprojectFittedStars()
705 if self.config.astrometryModel ==
"constrained":
707 sky_to_tan_projection,
708 chipOrder=self.config.astrometryChipOrder,
709 visitOrder=self.config.astrometryVisitOrder)
710 elif self.config.astrometryModel ==
"simple":
712 sky_to_tan_projection,
713 self.config.useInputWcs,
715 order=self.config.astrometrySimpleOrder)
718 chi2 = fit.computeChi2()
721 if self.config.writeChi2ContributionFiles:
722 baseName =
"astrometry_initial_chi2-{}.csv".format(dataName)
723 fit.saveChi2Contributions(baseName)
725 if not np.isfinite(chi2.chi2):
726 raise FloatingPointError(
'Initial chi2 is invalid: %s'%chi2)
727 self.log.info(
"Initialized: %s", str(chi2))
728 dumpMatrixFile =
"astrometry_preinit" if self.config.writeInitMatrix
else "" 731 if self.config.astrometryModel ==
"constrained":
732 fit.minimize(
"DistortionsVisit", dumpMatrixFile=dumpMatrixFile)
733 chi2 = fit.computeChi2()
734 self.log.info(str(chi2))
736 fit.minimize(
"Distortions", dumpMatrixFile=dumpMatrixFile)
737 chi2 = fit.computeChi2()
738 self.log.info(str(chi2))
739 fit.minimize(
"Positions")
740 chi2 = fit.computeChi2()
741 self.log.info(str(chi2))
742 fit.minimize(
"Distortions Positions")
743 chi2 = fit.computeChi2()
744 self.log.info(str(chi2))
745 if not np.isfinite(chi2.chi2):
746 raise FloatingPointError(
'Pre-iteration chi2 is invalid: %s'%chi2)
747 self.log.info(
"Fit prepared with %s", str(chi2))
751 self.config.maxAstrometrySteps,
753 "Distortions Positions",
754 doRankUpdate=self.config.astrometryDoRankUpdate,
760 return Astrometry(fit, model, sky_to_tan_projection)
762 def _check_stars(self, associations):
763 """Count measured and reference stars per ccd and warn/log them.""" 764 for ccdImage
in associations.getCcdImageList():
765 nMeasuredStars, nRefStars = ccdImage.countStars()
766 self.log.debug(
"ccdImage %s has %s measured and %s reference stars",
767 ccdImage.getName(), nMeasuredStars, nRefStars)
768 if nMeasuredStars < self.config.minMeasuredStarsPerCcd:
769 self.log.warn(
"ccdImage %s has only %s measuredStars (desired %s)",
770 ccdImage.getName(), nMeasuredStars, self.config.minMeasuredStarsPerCcd)
771 if nRefStars < self.config.minRefStarsPerCcd:
772 self.log.warn(
"ccdImage %s has only %s RefStars (desired %s)",
773 ccdImage.getName(), nRefStars, self.config.minRefStarsPerCcd)
775 def _iterate_fit(self, associations, fitter, max_steps, name, whatToFit,
779 """Run fitter.minimize up to max_steps times, returning the final chi2. 783 associations : `lsst.jointcal.Associations` 784 The star/reference star associations to fit. 785 fitter : `lsst.jointcal.FitterBase` 786 The fitter to use for minimization. 788 Maximum number of steps to run outlier rejection before declaring 790 name : {'photometry' or 'astrometry'} 791 What type of data are we fitting (for logs and debugging files). 793 Passed to ``fitter.minimize()`` to define the parameters to fit. 794 dataName : str, optional 795 Descriptive name for this dataset (e.g. tract and filter), 797 doRankUpdate : bool, optional 798 Do an Eigen rank update during minimization, or recompute the full 800 doLineSearch : bool, optional 801 Do a line search for the optimum step during minimization? 805 chi2: `lsst.jointcal.Chi2Statistic` 806 The final chi2 after the fit converges, or is forced to end. 811 Raised if the fitter fails with a non-finite value. 813 Raised if the fitter fails for some other reason; 814 log messages will provide further details. 816 dumpMatrixFile =
"%s_postinit" % name
if self.config.writeInitMatrix
else "" 817 for i
in range(max_steps):
818 result = fitter.minimize(whatToFit,
819 self.config.outlierRejectSigma,
820 doRankUpdate=doRankUpdate,
821 doLineSearch=doLineSearch,
822 dumpMatrixFile=dumpMatrixFile)
824 chi2 = fitter.computeChi2()
826 self.log.info(str(chi2))
827 if result == MinimizeResult.Converged:
829 self.log.debug(
"fit has converged - no more outliers - redo minimization " 830 "one more time in case we have lost accuracy in rank update.")
832 result = fitter.minimize(whatToFit, self.config.outlierRejectSigma)
833 chi2 = fitter.computeChi2()
834 self.log.info(
"Fit completed with: %s", str(chi2))
837 if chi2.chi2/chi2.ndof >= 4.0:
838 self.log.error(
"Potentially bad fit: High chi-squared/ndof.")
841 elif result == MinimizeResult.Chi2Increased:
842 self.log.warn(
"still some outliers but chi2 increases - retry")
843 elif result == MinimizeResult.NonFinite:
844 filename =
"{}_failure-nonfinite_chi2-{}.csv".format(name, dataName)
846 fitter.saveChi2Contributions(filename)
847 msg =
"Nonfinite value in chi2 minimization, cannot complete fit. Dumped star tables to: {}" 848 raise FloatingPointError(msg.format(filename))
849 elif result == MinimizeResult.Failed:
850 raise RuntimeError(
"Chi2 minimization failure, cannot complete fit.")
852 raise RuntimeError(
"Unxepected return code from minimize().")
854 self.log.error(
"%s failed to converge after %d steps"%(name, max_steps))
858 def _write_astrometry_results(self, associations, model, visit_ccd_to_dataRef):
860 Write the fitted astrometric results to a new 'jointcal_wcs' dataRef. 864 associations : lsst.jointcal.Associations 865 The star/reference star associations to fit. 866 model : lsst.jointcal.AstrometryModel 867 The astrometric model that was fit. 868 visit_ccd_to_dataRef : dict of Key: lsst.daf.persistence.ButlerDataRef 869 dict of ccdImage identifiers to dataRefs that were fit 872 ccdImageList = associations.getCcdImageList()
873 for ccdImage
in ccdImageList:
876 visit = ccdImage.visit
877 dataRef = visit_ccd_to_dataRef[(visit, ccd)]
878 self.log.info(
"Updating WCS for visit: %d, ccd: %d", visit, ccd)
879 skyWcs = model.makeSkyWcs(ccdImage)
881 dataRef.put(skyWcs,
'jointcal_wcs')
882 except pexExceptions.Exception
as e:
883 self.log.fatal(
'Failed to write updated Wcs: %s', str(e))
886 def _write_photometry_results(self, associations, model, visit_ccd_to_dataRef):
888 Write the fitted photometric results to a new 'jointcal_photoCalib' dataRef. 892 associations : lsst.jointcal.Associations 893 The star/reference star associations to fit. 894 model : lsst.jointcal.PhotometryModel 895 The photoometric model that was fit. 896 visit_ccd_to_dataRef : dict of Key: lsst.daf.persistence.ButlerDataRef 897 dict of ccdImage identifiers to dataRefs that were fit 900 ccdImageList = associations.getCcdImageList()
901 for ccdImage
in ccdImageList:
904 visit = ccdImage.visit
905 dataRef = visit_ccd_to_dataRef[(visit, ccd)]
906 self.log.info(
"Updating PhotoCalib for visit: %d, ccd: %d", visit, ccd)
907 photoCalib = model.toPhotoCalib(ccdImage)
909 dataRef.put(photoCalib,
'jointcal_photoCalib')
910 except pexExceptions.Exception
as e:
911 self.log.fatal(
'Failed to write updated PhotoCalib: %s', str(e))
def runDataRef(self, dataRefs, profile_jointcal=False)
def _build_ccdImage(self, dataRef, associations, jointcalControl)
def _fit_photometry(self, associations, dataName=None)
def getTargetList(parsedCmd, kwargs)
def _fit_astrometry(self, associations, dataName=None)
def _check_star_lists(self, associations, name)
The class that implements the relations between MeasuredStar and FittedStar.
A projection handler in which all CCDs from the same visit have the same tangent point.
std::string getPackageDir(std::string const &packageName)
this is the model used to fit independent CCDs, meaning that there is no instrument model...
def _iterate_fit(self, associations, fitter, max_steps, name, whatToFit, dataName="", doRankUpdate=True, doLineSearch=False)
def _write_photometry_results(self, associations, model, visit_ccd_to_dataRef)
def _check_stars(self, associations)
Class that handles the photometric least squares problem.
Class that handles the astrometric least squares problem.
def add_measurement(job, name, value)
def _do_load_refcat_and_fit(self, associations, defaultFilter, center, radius, name="", refObjLoader=None, filters=[], fit_function=None, tract=None, profile_jointcal=False, match_cut=3.0, reject_bad_fluxes=False)
This is the model used to fit mappings as the combination of a transformation depending on the chip n...
def _write_astrometry_results(self, associations, model, visit_ccd_to_dataRef)
def __init__(self, butler=None, profile_jointcal=False, kwargs)