33 from lsst.verify
import Job, Measurement
38 from .dataIds
import PerTractCcdDataIdContainer
43 __all__ = [
"JointcalConfig",
"JointcalRunner",
"JointcalTask"]
45 Photometry = collections.namedtuple(
'Photometry', (
'fit',
'model'))
46 Astrometry = collections.namedtuple(
'Astrometry', (
'fit',
'model',
'sky_to_tan_projection'))
51 meas = Measurement(job.metrics[name], value)
52 job.measurements.insert(meas)
56 """Subclass of TaskRunner for jointcalTask 58 jointcalTask.runDataRef() takes a number of arguments, one of which is a list of dataRefs 59 extracted from the command line (whereas most CmdLineTasks' runDataRef methods take 60 single dataRef, are are called repeatedly). This class transforms the processed 61 arguments generated by the ArgumentParser into the arguments expected by 62 Jointcal.runDataRef(). 64 See pipeBase.TaskRunner for more information. 70 Return a list of tuples per tract, each containing (dataRefs, kwargs). 72 Jointcal operates on lists of dataRefs simultaneously. 74 kwargs[
'profile_jointcal'] = parsedCmd.profile_jointcal
75 kwargs[
'butler'] = parsedCmd.butler
79 for ref
in parsedCmd.id.refList:
80 refListDict.setdefault(ref.dataId[
"tract"], []).append(ref)
82 result = [(refListDict[tract], kwargs)
for tract
in sorted(refListDict.keys())]
90 Arguments for Task.runDataRef() 95 if self.doReturnResults is False: 97 - ``exitStatus``: 0 if the task completed successfully, 1 otherwise. 99 if self.doReturnResults is True: 101 - ``result``: the result of calling jointcal.runDataRef() 102 - ``exitStatus``: 0 if the task completed successfully, 1 otherwise. 107 dataRefList, kwargs = args
108 butler = kwargs.pop(
'butler')
109 task = self.TaskClass(config=self.config, log=self.log, butler=butler)
112 result = task.runDataRef(dataRefList, **kwargs)
113 exitStatus = result.exitStatus
114 job_path = butler.get(
'verify_job_filename')
115 result.job.write(job_path[0])
116 except Exception
as e:
121 eName = type(e).__name__
122 tract = dataRefList[0].dataId[
'tract']
123 task.log.fatal(
"Failed processing tract %s, %s: %s", tract, eName, e)
125 if self.doReturnResults:
126 return pipeBase.Struct(result=result, exitStatus=exitStatus)
128 return pipeBase.Struct(exitStatus=exitStatus)
132 """Config for JointcalTask""" 134 doAstrometry = pexConfig.Field(
135 doc=
"Fit astrometry and write the fitted result.",
139 doPhotometry = pexConfig.Field(
140 doc=
"Fit photometry and write the fitted result.",
144 coaddName = pexConfig.Field(
145 doc=
"Type of coadd, typically deep or goodSeeing",
149 positionErrorPedestal = pexConfig.Field(
150 doc=
"Systematic term to apply to the measured position error (pixels)",
154 photometryErrorPedestal = pexConfig.Field(
155 doc=
"Systematic term to apply to the measured error on flux or magnitude as a " 156 "fraction of source flux or magnitude delta (e.g. 0.05 is 5% of flux or +50 millimag).",
161 matchCut = pexConfig.Field(
162 doc=
"Matching radius between fitted and reference stars (arcseconds)",
166 minMeasurements = pexConfig.Field(
167 doc=
"Minimum number of associated measured stars for a fitted star to be included in the fit",
171 minMeasuredStarsPerCcd = pexConfig.Field(
172 doc=
"Minimum number of measuredStars per ccdImage before printing warnings",
176 minRefStarsPerCcd = pexConfig.Field(
177 doc=
"Minimum number of measuredStars per ccdImage before printing warnings",
181 allowLineSearch = pexConfig.Field(
182 doc=
"Allow a line search during minimization, if it is reasonable for the model" 183 " (models with a significant non-linear component, e.g. constrainedPhotometry).",
187 astrometrySimpleOrder = pexConfig.Field(
188 doc=
"Polynomial order for fitting the simple astrometry model.",
192 astrometryChipOrder = pexConfig.Field(
193 doc=
"Order of the per-chip transform for the constrained astrometry model.",
197 astrometryVisitOrder = pexConfig.Field(
198 doc=
"Order of the per-visit transform for the constrained astrometry model.",
202 useInputWcs = pexConfig.Field(
203 doc=
"Use the input calexp WCSs to initialize a SimpleAstrometryModel.",
207 astrometryModel = pexConfig.ChoiceField(
208 doc=
"Type of model to fit to astrometry",
210 default=
"constrained",
211 allowed={
"simple":
"One polynomial per ccd",
212 "constrained":
"One polynomial per ccd, and one polynomial per visit"}
214 photometryModel = pexConfig.ChoiceField(
215 doc=
"Type of model to fit to photometry",
217 default=
"constrainedMagnitude",
218 allowed={
"simpleFlux":
"One constant zeropoint per ccd and visit, fitting in flux space.",
219 "constrainedFlux":
"Constrained zeropoint per ccd, and one polynomial per visit," 220 " fitting in flux space.",
221 "simpleMagnitude":
"One constant zeropoint per ccd and visit," 222 " fitting in magnitude space.",
223 "constrainedMagnitude":
"Constrained zeropoint per ccd, and one polynomial per visit," 224 " fitting in magnitude space.",
227 photometryVisitOrder = pexConfig.Field(
228 doc=
"Order of the per-visit polynomial transform for the constrained photometry model.",
232 photometryDoRankUpdate = pexConfig.Field(
233 doc=
"Do the rank update step during minimization. " 234 "Skipping this can help deal with models that are too non-linear.",
238 astrometryDoRankUpdate = pexConfig.Field(
239 doc=
"Do the rank update step during minimization (should not change the astrometry fit). " 240 "Skipping this can help deal with models that are too non-linear.",
244 outlierRejectSigma = pexConfig.Field(
245 doc=
"How many sigma to reject outliers at during minimization.",
249 maxPhotometrySteps = pexConfig.Field(
250 doc=
"Maximum number of minimize iterations to take when fitting photometry.",
254 maxAstrometrySteps = pexConfig.Field(
255 doc=
"Maximum number of minimize iterations to take when fitting photometry.",
259 astrometryRefObjLoader = pexConfig.ConfigurableField(
260 target=LoadIndexedReferenceObjectsTask,
261 doc=
"Reference object loader for astrometric fit",
263 photometryRefObjLoader = pexConfig.ConfigurableField(
264 target=LoadIndexedReferenceObjectsTask,
265 doc=
"Reference object loader for photometric fit",
267 sourceSelector = sourceSelectorRegistry.makeField(
268 doc=
"How to select sources for cross-matching",
271 writeInitMatrix = pexConfig.Field(
273 doc=
"Write the pre/post-initialization Hessian and gradient to text files, for debugging." 274 "The output files will be of the form 'astrometry_preinit-mat.txt', in the current directory." 275 "Note that these files are the dense versions of the matrix, and so may be very large.",
278 writeChi2ContributionFiles = pexConfig.Field(
280 doc=
"Write initial/final fit files containing the contributions to chi2.",
283 sourceFluxType = pexConfig.Field(
285 doc=
"Source flux field to use in source selection and to get fluxes from the catalog.",
291 sourceSelector.setDefaults()
293 sourceSelector.badFlags.extend([
"slot_Shape_flag"])
299 """Jointly astrometrically and photometrically calibrate a group of images.""" 301 ConfigClass = JointcalConfig
302 RunnerClass = JointcalRunner
303 _DefaultName =
"jointcal" 305 def __init__(self, butler=None, profile_jointcal=False, **kwargs):
307 Instantiate a JointcalTask. 311 butler : lsst.daf.persistence.Butler 312 The butler is passed to the refObjLoader constructor in case it is 313 needed. Ignored if the refObjLoader argument provides a loader directly. 314 Used to initialize the astrometry and photometry refObjLoaders. 315 profile_jointcal : bool 316 set to True to profile different stages of this jointcal run. 318 pipeBase.CmdLineTask.__init__(self, **kwargs)
320 self.makeSubtask(
"sourceSelector")
321 if self.config.doAstrometry:
322 self.makeSubtask(
'astrometryRefObjLoader', butler=butler)
323 if self.config.doPhotometry:
324 self.makeSubtask(
'photometryRefObjLoader', butler=butler)
327 self.
job = Job.load_metrics_package(subset=
'jointcal')
331 def _getConfigName(self):
334 def _getMetadataName(self):
338 def _makeArgumentParser(cls):
339 """Create an argument parser""" 341 parser.add_argument(
"--profile_jointcal", default=
False, action=
"store_true",
342 help=
"Profile steps of jointcal separately.")
343 parser.add_id_argument(
"--id",
"calexp", help=
"data ID, e.g. --id visit=6789 ccd=0..9",
344 ContainerClass=PerTractCcdDataIdContainer)
347 def _build_ccdImage(self, dataRef, associations, jointcalControl):
349 Extract the necessary things from this dataRef to add a new ccdImage. 353 dataRef : lsst.daf.persistence.ButlerDataRef 354 dataRef to extract info from. 355 associations : lsst.jointcal.Associations 356 object to add the info to, to construct a new CcdImage 357 jointcalControl : jointcal.JointcalControl 358 control object for associations management 363 wcs : lsst.afw.geom.SkyWcs 364 the TAN WCS of this image, read from the calexp 366 a key to identify this dataRef by its visit and ccd ids 370 if "visit" in dataRef.dataId.keys():
371 visit = dataRef.dataId[
"visit"]
373 visit = dataRef.getButler().queryMetadata(
"calexp", (
"visit"), dataRef.dataId)[0]
375 src = dataRef.get(
"src", flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS, immediate=
True)
377 visitInfo = dataRef.get(
'calexp_visitInfo')
378 detector = dataRef.get(
'calexp_detector')
379 ccdId = detector.getId()
380 calib = dataRef.get(
'calexp_calib')
381 tanWcs = dataRef.get(
'calexp_wcs')
382 bbox = dataRef.get(
'calexp_bbox')
383 filt = dataRef.get(
'calexp_filter')
384 filterName = filt.getName()
385 fluxMag0 = calib.getFluxMag0()
387 referenceFlux = 1e23 * 10**(48.6 / -2.5) * 1e9
388 photoCalib = afwImage.PhotoCalib(referenceFlux/fluxMag0[0],
389 referenceFlux*fluxMag0[1]/fluxMag0[0]**2, bbox)
391 goodSrc = self.sourceSelector.run(src)
393 if len(goodSrc.sourceCat) == 0:
394 self.log.warn(
"No sources selected in visit %s ccd %s", visit, ccdId)
396 self.log.info(
"%d sources selected in visit %d ccd %d", len(goodSrc.sourceCat), visit, ccdId)
397 associations.createCcdImage(goodSrc.sourceCat,
408 Result = collections.namedtuple(
'Result_from_build_CcdImage', (
'wcs',
'key',
'filter'))
409 Key = collections.namedtuple(
'Key', (
'visit',
'ccd'))
410 return Result(tanWcs, Key(visit, ccdId), filterName)
415 Jointly calibrate the astrometry and photometry across a set of images. 419 dataRefs : list of lsst.daf.persistence.ButlerDataRef 420 List of data references to the exposures to be fit. 421 profile_jointcal : bool 422 Profile the individual steps of jointcal. 428 * dataRefs: the provided data references that were fit (with updated WCSs) 429 * oldWcsList: the original WCS from each dataRef 430 * metrics: dictionary of internally-computed metrics for testing/validation. 432 if len(dataRefs) == 0:
433 raise ValueError(
'Need a non-empty list of data references!')
437 sourceFluxField =
"slot_%sFlux" % (self.config.sourceFluxType,)
441 visit_ccd_to_dataRef = {}
444 load_cat_prof_file =
'jointcal_build_ccdImage.prof' if profile_jointcal
else '' 445 with pipeBase.cmdLineTask.profile(load_cat_prof_file):
448 camera = dataRefs[0].get(
'camera', immediate=
True)
452 oldWcsList.append(result.wcs)
453 visit_ccd_to_dataRef[result.key] = ref
454 filters.append(result.filter)
455 filters = collections.Counter(filters)
457 associations.computeCommonTangentPoint()
462 bbox = associations.getRaDecBBox()
463 bboxCenter = bbox.getCenter()
464 center = afwGeom.SpherePoint(bboxCenter[0], bboxCenter[1], afwGeom.degrees)
465 bboxMax = bbox.getMax()
466 corner = afwGeom.SpherePoint(bboxMax[0], bboxMax[1], afwGeom.degrees)
467 radius = center.separation(corner).asRadians()
472 raise RuntimeError(
"astrometry_net_data is not setup")
475 defaultFilter = filters.most_common(1)[0][0]
476 self.log.debug(
"Using %s band for reference flux", defaultFilter)
479 tract = dataRefs[0].dataId[
'tract']
481 if self.config.doAstrometry:
484 refObjLoader=self.astrometryRefObjLoader,
486 profile_jointcal=profile_jointcal,
492 if self.config.doPhotometry:
495 refObjLoader=self.photometryRefObjLoader,
497 profile_jointcal=profile_jointcal,
500 reject_bad_fluxes=
True)
505 return pipeBase.Struct(dataRefs=dataRefs,
506 oldWcsList=oldWcsList,
508 exitStatus=exitStatus)
510 def _do_load_refcat_and_fit(self, associations, defaultFilter, center, radius,
511 name="", refObjLoader=None, filters=[], fit_function=None,
512 tract=None, profile_jointcal=False, match_cut=3.0,
513 reject_bad_fluxes=False):
514 """Load reference catalog, perform the fit, and return the result. 518 associations : lsst.jointcal.Associations 519 The star/reference star associations to fit. 521 filter to load from reference catalog. 522 center : lsst.afw.geom.SpherePoint 523 ICRS center of field to load from reference catalog. 524 radius : lsst.afw.geom.Angle 525 On-sky radius to load from reference catalog. 527 Name of thing being fit: "Astrometry" or "Photometry". 528 refObjLoader : lsst.meas.algorithms.LoadReferenceObjectsTask 529 Reference object loader to load from for fit. 530 filters : list of str, optional 531 List of filters to load from the reference catalog. 532 fit_function : function 533 function to call to perform fit (takes associations object). 535 Name of tract currently being fit. 536 profile_jointcal : bool, optional 537 Separately profile the fitting step. 538 match_cut : float, optional 539 Radius in arcseconds to find cross-catalog matches to during 540 associations.associateCatalogs. 541 reject_bad_fluxes : bool, optional 542 Reject refCat sources with NaN/inf flux or NaN/0 fluxErr. 546 Result of `fit_function()` 548 self.log.info(
"====== Now processing %s...", name)
551 associations.associateCatalogs(match_cut)
553 associations.fittedStarListSize())
555 skyCircle = refObjLoader.loadSkyCircle(center,
556 afwGeom.Angle(radius, afwGeom.radians),
560 if not skyCircle.refCat.isContiguous():
561 refCat = skyCircle.refCat.copy(deep=
True)
563 refCat = skyCircle.refCat
570 filtKeys = lsst.meas.algorithms.getRefFluxKeys(refCat.schema, filt)
572 refFluxes[filt] = 1e9*refCat.get(filtKeys[0])
573 refFluxErrs[filt] = 1e9*refCat.get(filtKeys[1])
576 refCat[skyCircle.fluxField] *= 1e9
578 refCat[skyCircle.fluxField+
'Err'] *= 1e9
583 associations.collectRefStars(refCat, self.config.matchCut*afwGeom.arcseconds,
584 skyCircle.fluxField, refFluxes, refFluxErrs, reject_bad_fluxes)
586 associations.refStarListSize())
588 associations.prepareFittedStars(self.config.minMeasurements)
592 associations.nFittedStarsWithAssociatedRefStar())
594 associations.fittedStarListSize())
596 associations.nCcdImagesValidForFit())
598 load_cat_prof_file =
'jointcal_fit_%s.prof'%name
if profile_jointcal
else '' 599 dataName =
"{}_{}".format(tract, defaultFilter)
600 with pipeBase.cmdLineTask.profile(load_cat_prof_file):
601 result = fit_function(associations, dataName)
604 if self.config.writeChi2ContributionFiles:
605 baseName =
"{}_final_chi2-{}.csv".format(name, dataName)
606 result.fit.saveChi2Contributions(baseName)
610 def _check_star_lists(self, associations, name):
612 if associations.nCcdImagesValidForFit() == 0:
613 raise RuntimeError(
'No images in the ccdImageList!')
614 if associations.fittedStarListSize() == 0:
615 raise RuntimeError(
'No stars in the {} fittedStarList!'.format(name))
616 if associations.refStarListSize() == 0:
617 raise RuntimeError(
'No stars in the {} reference star list!'.format(name))
619 def _logChi2AndValidate(self, associations, fit, model, chi2Label="Model"):
620 """Compute chi2, log it, validate the model, and return chi2.""" 621 chi2 = fit.computeChi2()
622 self.log.info(
"%s %s", chi2Label, chi2)
624 if not np.isfinite(chi2.chi2):
625 raise FloatingPointError(
'%s chi2 is invalid: %s', chi2Label, chi2)
626 if not model.validate(associations.getCcdImageList()):
627 raise ValueError(
"Model is not valid: check log messages for warnings.")
630 def _fit_photometry(self, associations, dataName=None):
632 Fit the photometric data. 636 associations : lsst.jointcal.Associations 637 The star/reference star associations to fit. 639 Name of the data being processed (e.g. "1234_HSC-Y"), for 640 identifying debugging files. 645 fit : lsst.jointcal.PhotometryFit 646 The photometric fitter used to perform the fit. 647 model : lsst.jointcal.PhotometryModel 648 The photometric model that was fit. 650 self.log.info(
"=== Starting photometric fitting...")
653 if self.config.photometryModel ==
"constrainedFlux":
656 visitOrder=self.config.photometryVisitOrder,
657 errorPedestal=self.config.photometryErrorPedestal)
659 doLineSearch = self.config.allowLineSearch
660 elif self.config.photometryModel ==
"constrainedMagnitude":
663 visitOrder=self.config.photometryVisitOrder,
664 errorPedestal=self.config.photometryErrorPedestal)
666 doLineSearch = self.config.allowLineSearch
667 elif self.config.photometryModel ==
"simpleFlux":
669 errorPedestal=self.config.photometryErrorPedestal)
671 elif self.config.photometryModel ==
"simpleMagnitude":
673 errorPedestal=self.config.photometryErrorPedestal)
681 if self.config.writeChi2ContributionFiles:
682 baseName =
"photometry_initial_chi2-{}.csv".format(dataName)
683 fit.saveChi2Contributions(baseName)
687 dumpMatrixFile =
"photometry_preinit" if self.config.writeInitMatrix
else "" 688 if self.config.photometryModel.startswith(
"constrained"):
691 fit.minimize(
"ModelVisit", dumpMatrixFile=dumpMatrixFile)
695 fit.minimize(
"Model", doLineSearch=doLineSearch, dumpMatrixFile=dumpMatrixFile)
698 fit.minimize(
"Fluxes")
701 fit.minimize(
"Model Fluxes", doLineSearch=doLineSearch)
704 model.freezeErrorTransform()
705 self.log.debug(
"Photometry error scales are frozen.")
709 self.config.maxPhotometrySteps,
712 doRankUpdate=self.config.photometryDoRankUpdate,
713 doLineSearch=doLineSearch,
720 def _fit_astrometry(self, associations, dataName=None):
722 Fit the astrometric data. 726 associations : lsst.jointcal.Associations 727 The star/reference star associations to fit. 729 Name of the data being processed (e.g. "1234_HSC-Y"), for 730 identifying debugging files. 735 fit : lsst.jointcal.AstrometryFit 736 The astrometric fitter used to perform the fit. 737 model : lsst.jointcal.AstrometryModel 738 The astrometric model that was fit. 739 sky_to_tan_projection : lsst.jointcal.ProjectionHandler 740 The model for the sky to tangent plane projection that was used in the fit. 743 self.log.info(
"=== Starting astrometric fitting...")
745 associations.deprojectFittedStars()
752 if self.config.astrometryModel ==
"constrained":
754 sky_to_tan_projection,
755 chipOrder=self.config.astrometryChipOrder,
756 visitOrder=self.config.astrometryVisitOrder)
757 elif self.config.astrometryModel ==
"simple":
759 sky_to_tan_projection,
760 self.config.useInputWcs,
762 order=self.config.astrometrySimpleOrder)
769 if self.config.writeChi2ContributionFiles:
770 baseName =
"astrometry_initial_chi2-{}.csv".format(dataName)
771 fit.saveChi2Contributions(baseName)
773 dumpMatrixFile =
"astrometry_preinit" if self.config.writeInitMatrix
else "" 776 if self.config.astrometryModel ==
"constrained":
777 fit.minimize(
"DistortionsVisit", dumpMatrixFile=dumpMatrixFile)
781 fit.minimize(
"Distortions", dumpMatrixFile=dumpMatrixFile)
784 fit.minimize(
"Positions")
787 fit.minimize(
"Distortions Positions")
792 self.config.maxAstrometrySteps,
794 "Distortions Positions",
795 doRankUpdate=self.config.astrometryDoRankUpdate,
801 return Astrometry(fit, model, sky_to_tan_projection)
803 def _check_stars(self, associations):
804 """Count measured and reference stars per ccd and warn/log them.""" 805 for ccdImage
in associations.getCcdImageList():
806 nMeasuredStars, nRefStars = ccdImage.countStars()
807 self.log.debug(
"ccdImage %s has %s measured and %s reference stars",
808 ccdImage.getName(), nMeasuredStars, nRefStars)
809 if nMeasuredStars < self.config.minMeasuredStarsPerCcd:
810 self.log.warn(
"ccdImage %s has only %s measuredStars (desired %s)",
811 ccdImage.getName(), nMeasuredStars, self.config.minMeasuredStarsPerCcd)
812 if nRefStars < self.config.minRefStarsPerCcd:
813 self.log.warn(
"ccdImage %s has only %s RefStars (desired %s)",
814 ccdImage.getName(), nRefStars, self.config.minRefStarsPerCcd)
816 def _iterate_fit(self, associations, fitter, max_steps, name, whatToFit,
820 """Run fitter.minimize up to max_steps times, returning the final chi2. 824 associations : `lsst.jointcal.Associations` 825 The star/reference star associations to fit. 826 fitter : `lsst.jointcal.FitterBase` 827 The fitter to use for minimization. 829 Maximum number of steps to run outlier rejection before declaring 831 name : {'photometry' or 'astrometry'} 832 What type of data are we fitting (for logs and debugging files). 834 Passed to ``fitter.minimize()`` to define the parameters to fit. 835 dataName : str, optional 836 Descriptive name for this dataset (e.g. tract and filter), 838 doRankUpdate : bool, optional 839 Do an Eigen rank update during minimization, or recompute the full 841 doLineSearch : bool, optional 842 Do a line search for the optimum step during minimization? 846 chi2: `lsst.jointcal.Chi2Statistic` 847 The final chi2 after the fit converges, or is forced to end. 852 Raised if the fitter fails with a non-finite value. 854 Raised if the fitter fails for some other reason; 855 log messages will provide further details. 857 dumpMatrixFile =
"%s_postinit" % name
if self.config.writeInitMatrix
else "" 858 for i
in range(max_steps):
859 result = fitter.minimize(whatToFit,
860 self.config.outlierRejectSigma,
861 doRankUpdate=doRankUpdate,
862 doLineSearch=doLineSearch,
863 dumpMatrixFile=dumpMatrixFile)
867 if result == MinimizeResult.Converged:
869 self.log.debug(
"fit has converged - no more outliers - redo minimization " 870 "one more time in case we have lost accuracy in rank update.")
872 result = fitter.minimize(whatToFit, self.config.outlierRejectSigma)
876 if chi2.chi2/chi2.ndof >= 4.0:
877 self.log.error(
"Potentially bad fit: High chi-squared/ndof.")
880 elif result == MinimizeResult.Chi2Increased:
881 self.log.warn(
"still some outliers but chi2 increases - retry")
882 elif result == MinimizeResult.NonFinite:
883 filename =
"{}_failure-nonfinite_chi2-{}.csv".format(name, dataName)
885 fitter.saveChi2Contributions(filename)
886 msg =
"Nonfinite value in chi2 minimization, cannot complete fit. Dumped star tables to: {}" 887 raise FloatingPointError(msg.format(filename))
888 elif result == MinimizeResult.Failed:
889 raise RuntimeError(
"Chi2 minimization failure, cannot complete fit.")
891 raise RuntimeError(
"Unxepected return code from minimize().")
893 self.log.error(
"%s failed to converge after %d steps"%(name, max_steps))
897 def _write_astrometry_results(self, associations, model, visit_ccd_to_dataRef):
899 Write the fitted astrometric results to a new 'jointcal_wcs' dataRef. 903 associations : lsst.jointcal.Associations 904 The star/reference star associations to fit. 905 model : lsst.jointcal.AstrometryModel 906 The astrometric model that was fit. 907 visit_ccd_to_dataRef : dict of Key: lsst.daf.persistence.ButlerDataRef 908 dict of ccdImage identifiers to dataRefs that were fit 911 ccdImageList = associations.getCcdImageList()
912 for ccdImage
in ccdImageList:
915 visit = ccdImage.visit
916 dataRef = visit_ccd_to_dataRef[(visit, ccd)]
917 self.log.info(
"Updating WCS for visit: %d, ccd: %d", visit, ccd)
918 skyWcs = model.makeSkyWcs(ccdImage)
920 dataRef.put(skyWcs,
'jointcal_wcs')
921 except pexExceptions.Exception
as e:
922 self.log.fatal(
'Failed to write updated Wcs: %s', str(e))
925 def _write_photometry_results(self, associations, model, visit_ccd_to_dataRef):
927 Write the fitted photometric results to a new 'jointcal_photoCalib' dataRef. 931 associations : lsst.jointcal.Associations 932 The star/reference star associations to fit. 933 model : lsst.jointcal.PhotometryModel 934 The photoometric model that was fit. 935 visit_ccd_to_dataRef : dict of Key: lsst.daf.persistence.ButlerDataRef 936 dict of ccdImage identifiers to dataRefs that were fit 939 ccdImageList = associations.getCcdImageList()
940 for ccdImage
in ccdImageList:
943 visit = ccdImage.visit
944 dataRef = visit_ccd_to_dataRef[(visit, ccd)]
945 self.log.info(
"Updating PhotoCalib for visit: %d, ccd: %d", visit, ccd)
946 photoCalib = model.toPhotoCalib(ccdImage)
948 dataRef.put(photoCalib,
'jointcal_photoCalib')
949 except pexExceptions.Exception
as e:
950 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)
def _logChi2AndValidate(self, associations, fit, model, chi2Label="Model")
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)