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)
325 if self.config.doPhotometry:
326 self.makeSubtask(
'photometryRefObjLoader', butler=butler)
331 self.
job = Job.load_metrics_package(subset=
'jointcal')
335 def _getConfigName(self):
338 def _getMetadataName(self):
342 def _makeArgumentParser(cls):
343 """Create an argument parser""" 345 parser.add_argument(
"--profile_jointcal", default=
False, action=
"store_true",
346 help=
"Profile steps of jointcal separately.")
347 parser.add_id_argument(
"--id",
"calexp", help=
"data ID, e.g. --id visit=6789 ccd=0..9",
348 ContainerClass=PerTractCcdDataIdContainer)
351 def _build_ccdImage(self, dataRef, associations, jointcalControl):
353 Extract the necessary things from this dataRef to add a new ccdImage. 357 dataRef : lsst.daf.persistence.ButlerDataRef 358 dataRef to extract info from. 359 associations : lsst.jointcal.Associations 360 object to add the info to, to construct a new CcdImage 361 jointcalControl : jointcal.JointcalControl 362 control object for associations management 367 wcs : lsst.afw.geom.SkyWcs 368 the TAN WCS of this image, read from the calexp 370 a key to identify this dataRef by its visit and ccd ids 374 if "visit" in dataRef.dataId.keys():
375 visit = dataRef.dataId[
"visit"]
377 visit = dataRef.getButler().queryMetadata(
"calexp", (
"visit"), dataRef.dataId)[0]
379 src = dataRef.get(
"src", flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS, immediate=
True)
381 visitInfo = dataRef.get(
'calexp_visitInfo')
382 detector = dataRef.get(
'calexp_detector')
383 ccdId = detector.getId()
384 calib = dataRef.get(
'calexp_calib')
385 tanWcs = dataRef.get(
'calexp_wcs')
386 bbox = dataRef.get(
'calexp_bbox')
387 filt = dataRef.get(
'calexp_filter')
388 filterName = filt.getName()
389 fluxMag0 = calib.getFluxMag0()
391 referenceFlux = 1e23 * 10**(48.6 / -2.5) * 1e9
392 photoCalib = afwImage.PhotoCalib(referenceFlux/fluxMag0[0],
393 referenceFlux*fluxMag0[1]/fluxMag0[0]**2, bbox)
395 goodSrc = self.sourceSelector.run(src)
397 if len(goodSrc.sourceCat) == 0:
398 self.log.warn(
"No sources selected in visit %s ccd %s", visit, ccdId)
400 self.log.info(
"%d sources selected in visit %d ccd %d", len(goodSrc.sourceCat), visit, ccdId)
401 associations.createCcdImage(goodSrc.sourceCat,
412 Result = collections.namedtuple(
'Result_from_build_CcdImage', (
'wcs',
'key',
'filter'))
413 Key = collections.namedtuple(
'Key', (
'visit',
'ccd'))
414 return Result(tanWcs, Key(visit, ccdId), filterName)
419 Jointly calibrate the astrometry and photometry across a set of images. 423 dataRefs : list of lsst.daf.persistence.ButlerDataRef 424 List of data references to the exposures to be fit. 425 profile_jointcal : bool 426 Profile the individual steps of jointcal. 432 * dataRefs: the provided data references that were fit (with updated WCSs) 433 * oldWcsList: the original WCS from each dataRef 434 * metrics: dictionary of internally-computed metrics for testing/validation. 436 if len(dataRefs) == 0:
437 raise ValueError(
'Need a non-empty list of data references!')
441 sourceFluxField =
"slot_%sFlux" % (self.config.sourceFluxType,)
445 visit_ccd_to_dataRef = {}
448 load_cat_prof_file =
'jointcal_build_ccdImage.prof' if profile_jointcal
else '' 449 with pipeBase.cmdLineTask.profile(load_cat_prof_file):
452 camera = dataRefs[0].get(
'camera', immediate=
True)
456 oldWcsList.append(result.wcs)
457 visit_ccd_to_dataRef[result.key] = ref
458 filters.append(result.filter)
459 filters = collections.Counter(filters)
461 associations.computeCommonTangentPoint()
466 bbox = associations.getRaDecBBox()
467 bboxCenter = bbox.getCenter()
468 center = afwGeom.SpherePoint(bboxCenter[0], bboxCenter[1], afwGeom.degrees)
469 bboxMax = bbox.getMax()
470 corner = afwGeom.SpherePoint(bboxMax[0], bboxMax[1], afwGeom.degrees)
471 radius = center.separation(corner).asRadians()
476 raise RuntimeError(
"astrometry_net_data is not setup")
479 defaultFilter = filters.most_common(1)[0][0]
480 self.log.debug(
"Using %s band for reference flux", defaultFilter)
483 tract = dataRefs[0].dataId[
'tract']
485 if self.config.doAstrometry:
490 profile_jointcal=profile_jointcal,
496 if self.config.doPhotometry:
501 profile_jointcal=profile_jointcal,
504 reject_bad_fluxes=
True)
509 return pipeBase.Struct(dataRefs=dataRefs,
510 oldWcsList=oldWcsList,
514 defaultFilter=defaultFilter,
515 exitStatus=exitStatus)
517 def _do_load_refcat_and_fit(self, associations, defaultFilter, center, radius,
518 name="", refObjLoader=None, filters=[], fit_function=None,
519 tract=None, profile_jointcal=False, match_cut=3.0,
520 reject_bad_fluxes=False):
521 """Load reference catalog, perform the fit, and return the result. 525 associations : lsst.jointcal.Associations 526 The star/reference star associations to fit. 528 filter to load from reference catalog. 529 center : lsst.afw.geom.SpherePoint 530 ICRS center of field to load from reference catalog. 531 radius : lsst.afw.geom.Angle 532 On-sky radius to load from reference catalog. 534 Name of thing being fit: "Astrometry" or "Photometry". 535 refObjLoader : lsst.meas.algorithms.LoadReferenceObjectsTask 536 Reference object loader to load from for fit. 537 filters : list of str, optional 538 List of filters to load from the reference catalog. 539 fit_function : function 540 function to call to perform fit (takes associations object). 542 Name of tract currently being fit. 543 profile_jointcal : bool, optional 544 Separately profile the fitting step. 545 match_cut : float, optional 546 Radius in arcseconds to find cross-catalog matches to during 547 associations.associateCatalogs. 548 reject_bad_fluxes : bool, optional 549 Reject refCat sources with NaN/inf flux or NaN/0 fluxErr. 553 Result of `fit_function()` 555 self.log.info(
"====== Now processing %s...", name)
558 associations.associateCatalogs(match_cut)
560 associations.fittedStarListSize())
562 skyCircle = refObjLoader.loadSkyCircle(center,
563 afwGeom.Angle(radius, afwGeom.radians),
567 if not skyCircle.refCat.isContiguous():
568 refCat = skyCircle.refCat.copy(deep=
True)
570 refCat = skyCircle.refCat
577 filtKeys = lsst.meas.algorithms.getRefFluxKeys(refCat.schema, filt)
579 refFluxes[filt] = 1e9*refCat.get(filtKeys[0])
580 refFluxErrs[filt] = 1e9*refCat.get(filtKeys[1])
583 refCat[skyCircle.fluxField] *= 1e9
585 refCat[skyCircle.fluxField+
'Err'] *= 1e9
590 associations.collectRefStars(refCat, self.config.matchCut*afwGeom.arcseconds,
591 skyCircle.fluxField, refFluxes, refFluxErrs, reject_bad_fluxes)
593 associations.refStarListSize())
595 associations.prepareFittedStars(self.config.minMeasurements)
599 associations.nFittedStarsWithAssociatedRefStar())
601 associations.fittedStarListSize())
603 associations.nCcdImagesValidForFit())
605 load_cat_prof_file =
'jointcal_fit_%s.prof'%name
if profile_jointcal
else '' 606 dataName =
"{}_{}".format(tract, defaultFilter)
607 with pipeBase.cmdLineTask.profile(load_cat_prof_file):
608 result = fit_function(associations, dataName)
611 if self.config.writeChi2ContributionFiles:
612 baseName =
"{}_final_chi2-{}.csv".format(name, dataName)
613 result.fit.saveChi2Contributions(baseName)
617 def _check_star_lists(self, associations, name):
619 if associations.nCcdImagesValidForFit() == 0:
620 raise RuntimeError(
'No images in the ccdImageList!')
621 if associations.fittedStarListSize() == 0:
622 raise RuntimeError(
'No stars in the {} fittedStarList!'.format(name))
623 if associations.refStarListSize() == 0:
624 raise RuntimeError(
'No stars in the {} reference star list!'.format(name))
626 def _logChi2AndValidate(self, associations, fit, model, chi2Label="Model"):
627 """Compute chi2, log it, validate the model, and return chi2.""" 628 chi2 = fit.computeChi2()
629 self.log.info(
"%s %s", chi2Label, chi2)
631 if not np.isfinite(chi2.chi2):
632 raise FloatingPointError(
'%s chi2 is invalid: %s', chi2Label, chi2)
633 if not model.validate(associations.getCcdImageList()):
634 raise ValueError(
"Model is not valid: check log messages for warnings.")
637 def _fit_photometry(self, associations, dataName=None):
639 Fit the photometric data. 643 associations : lsst.jointcal.Associations 644 The star/reference star associations to fit. 646 Name of the data being processed (e.g. "1234_HSC-Y"), for 647 identifying debugging files. 652 fit : lsst.jointcal.PhotometryFit 653 The photometric fitter used to perform the fit. 654 model : lsst.jointcal.PhotometryModel 655 The photometric model that was fit. 657 self.log.info(
"=== Starting photometric fitting...")
660 if self.config.photometryModel ==
"constrainedFlux":
663 visitOrder=self.config.photometryVisitOrder,
664 errorPedestal=self.config.photometryErrorPedestal)
666 doLineSearch = self.config.allowLineSearch
667 elif self.config.photometryModel ==
"constrainedMagnitude":
670 visitOrder=self.config.photometryVisitOrder,
671 errorPedestal=self.config.photometryErrorPedestal)
673 doLineSearch = self.config.allowLineSearch
674 elif self.config.photometryModel ==
"simpleFlux":
676 errorPedestal=self.config.photometryErrorPedestal)
678 elif self.config.photometryModel ==
"simpleMagnitude":
680 errorPedestal=self.config.photometryErrorPedestal)
688 if self.config.writeChi2ContributionFiles:
689 baseName =
"photometry_initial_chi2-{}.csv".format(dataName)
690 fit.saveChi2Contributions(baseName)
694 dumpMatrixFile =
"photometry_preinit" if self.config.writeInitMatrix
else "" 695 if self.config.photometryModel.startswith(
"constrained"):
698 fit.minimize(
"ModelVisit", dumpMatrixFile=dumpMatrixFile)
702 fit.minimize(
"Model", doLineSearch=doLineSearch, dumpMatrixFile=dumpMatrixFile)
705 fit.minimize(
"Fluxes")
708 fit.minimize(
"Model Fluxes", doLineSearch=doLineSearch)
711 model.freezeErrorTransform()
712 self.log.debug(
"Photometry error scales are frozen.")
716 self.config.maxPhotometrySteps,
719 doRankUpdate=self.config.photometryDoRankUpdate,
720 doLineSearch=doLineSearch,
727 def _fit_astrometry(self, associations, dataName=None):
729 Fit the astrometric data. 733 associations : lsst.jointcal.Associations 734 The star/reference star associations to fit. 736 Name of the data being processed (e.g. "1234_HSC-Y"), for 737 identifying debugging files. 742 fit : lsst.jointcal.AstrometryFit 743 The astrometric fitter used to perform the fit. 744 model : lsst.jointcal.AstrometryModel 745 The astrometric model that was fit. 746 sky_to_tan_projection : lsst.jointcal.ProjectionHandler 747 The model for the sky to tangent plane projection that was used in the fit. 750 self.log.info(
"=== Starting astrometric fitting...")
752 associations.deprojectFittedStars()
759 if self.config.astrometryModel ==
"constrained":
761 sky_to_tan_projection,
762 chipOrder=self.config.astrometryChipOrder,
763 visitOrder=self.config.astrometryVisitOrder)
764 elif self.config.astrometryModel ==
"simple":
766 sky_to_tan_projection,
767 self.config.useInputWcs,
769 order=self.config.astrometrySimpleOrder)
776 if self.config.writeChi2ContributionFiles:
777 baseName =
"astrometry_initial_chi2-{}.csv".format(dataName)
778 fit.saveChi2Contributions(baseName)
780 dumpMatrixFile =
"astrometry_preinit" if self.config.writeInitMatrix
else "" 783 if self.config.astrometryModel ==
"constrained":
784 fit.minimize(
"DistortionsVisit", dumpMatrixFile=dumpMatrixFile)
788 fit.minimize(
"Distortions", dumpMatrixFile=dumpMatrixFile)
791 fit.minimize(
"Positions")
794 fit.minimize(
"Distortions Positions")
799 self.config.maxAstrometrySteps,
801 "Distortions Positions",
802 doRankUpdate=self.config.astrometryDoRankUpdate,
808 return Astrometry(fit, model, sky_to_tan_projection)
810 def _check_stars(self, associations):
811 """Count measured and reference stars per ccd and warn/log them.""" 812 for ccdImage
in associations.getCcdImageList():
813 nMeasuredStars, nRefStars = ccdImage.countStars()
814 self.log.debug(
"ccdImage %s has %s measured and %s reference stars",
815 ccdImage.getName(), nMeasuredStars, nRefStars)
816 if nMeasuredStars < self.config.minMeasuredStarsPerCcd:
817 self.log.warn(
"ccdImage %s has only %s measuredStars (desired %s)",
818 ccdImage.getName(), nMeasuredStars, self.config.minMeasuredStarsPerCcd)
819 if nRefStars < self.config.minRefStarsPerCcd:
820 self.log.warn(
"ccdImage %s has only %s RefStars (desired %s)",
821 ccdImage.getName(), nRefStars, self.config.minRefStarsPerCcd)
823 def _iterate_fit(self, associations, fitter, max_steps, name, whatToFit,
827 """Run fitter.minimize up to max_steps times, returning the final chi2. 831 associations : `lsst.jointcal.Associations` 832 The star/reference star associations to fit. 833 fitter : `lsst.jointcal.FitterBase` 834 The fitter to use for minimization. 836 Maximum number of steps to run outlier rejection before declaring 838 name : {'photometry' or 'astrometry'} 839 What type of data are we fitting (for logs and debugging files). 841 Passed to ``fitter.minimize()`` to define the parameters to fit. 842 dataName : str, optional 843 Descriptive name for this dataset (e.g. tract and filter), 845 doRankUpdate : bool, optional 846 Do an Eigen rank update during minimization, or recompute the full 848 doLineSearch : bool, optional 849 Do a line search for the optimum step during minimization? 853 chi2: `lsst.jointcal.Chi2Statistic` 854 The final chi2 after the fit converges, or is forced to end. 859 Raised if the fitter fails with a non-finite value. 861 Raised if the fitter fails for some other reason; 862 log messages will provide further details. 864 dumpMatrixFile =
"%s_postinit" % name
if self.config.writeInitMatrix
else "" 865 for i
in range(max_steps):
866 result = fitter.minimize(whatToFit,
867 self.config.outlierRejectSigma,
868 doRankUpdate=doRankUpdate,
869 doLineSearch=doLineSearch,
870 dumpMatrixFile=dumpMatrixFile)
874 if result == MinimizeResult.Converged:
876 self.log.debug(
"fit has converged - no more outliers - redo minimization " 877 "one more time in case we have lost accuracy in rank update.")
879 result = fitter.minimize(whatToFit, self.config.outlierRejectSigma)
883 if chi2.chi2/chi2.ndof >= 4.0:
884 self.log.error(
"Potentially bad fit: High chi-squared/ndof.")
887 elif result == MinimizeResult.Chi2Increased:
888 self.log.warn(
"still some outliers but chi2 increases - retry")
889 elif result == MinimizeResult.NonFinite:
890 filename =
"{}_failure-nonfinite_chi2-{}.csv".format(name, dataName)
892 fitter.saveChi2Contributions(filename)
893 msg =
"Nonfinite value in chi2 minimization, cannot complete fit. Dumped star tables to: {}" 894 raise FloatingPointError(msg.format(filename))
895 elif result == MinimizeResult.Failed:
896 raise RuntimeError(
"Chi2 minimization failure, cannot complete fit.")
898 raise RuntimeError(
"Unxepected return code from minimize().")
900 self.log.error(
"%s failed to converge after %d steps"%(name, max_steps))
904 def _write_astrometry_results(self, associations, model, visit_ccd_to_dataRef):
906 Write the fitted astrometric results to a new 'jointcal_wcs' dataRef. 910 associations : lsst.jointcal.Associations 911 The star/reference star associations to fit. 912 model : lsst.jointcal.AstrometryModel 913 The astrometric model that was fit. 914 visit_ccd_to_dataRef : dict of Key: lsst.daf.persistence.ButlerDataRef 915 dict of ccdImage identifiers to dataRefs that were fit 918 ccdImageList = associations.getCcdImageList()
919 for ccdImage
in ccdImageList:
922 visit = ccdImage.visit
923 dataRef = visit_ccd_to_dataRef[(visit, ccd)]
924 self.log.info(
"Updating WCS for visit: %d, ccd: %d", visit, ccd)
925 skyWcs = model.makeSkyWcs(ccdImage)
927 dataRef.put(skyWcs,
'jointcal_wcs')
928 except pexExceptions.Exception
as e:
929 self.log.fatal(
'Failed to write updated Wcs: %s', str(e))
932 def _write_photometry_results(self, associations, model, visit_ccd_to_dataRef):
934 Write the fitted photometric results to a new 'jointcal_photoCalib' dataRef. 938 associations : lsst.jointcal.Associations 939 The star/reference star associations to fit. 940 model : lsst.jointcal.PhotometryModel 941 The photoometric model that was fit. 942 visit_ccd_to_dataRef : dict of Key: lsst.daf.persistence.ButlerDataRef 943 dict of ccdImage identifiers to dataRefs that were fit 946 ccdImageList = associations.getCcdImageList()
947 for ccdImage
in ccdImageList:
950 visit = ccdImage.visit
951 dataRef = visit_ccd_to_dataRef[(visit, ccd)]
952 self.log.info(
"Updating PhotoCalib for visit: %d, ccd: %d", visit, ccd)
953 photoCalib = model.toPhotoCalib(ccdImage)
955 dataRef.put(photoCalib,
'jointcal_photoCalib')
956 except pexExceptions.Exception
as e:
957 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)