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()
386 photoCalib = afwImage.PhotoCalib(1.0/fluxMag0[0], fluxMag0[1]/fluxMag0[0]**2, bbox)
388 goodSrc = self.sourceSelector.run(src)
390 if len(goodSrc.sourceCat) == 0:
391 self.log.warn(
"No sources selected in visit %s ccd %s", visit, ccdId)
393 self.log.info(
"%d sources selected in visit %d ccd %d", len(goodSrc.sourceCat), visit, ccdId)
394 associations.createCcdImage(goodSrc.sourceCat,
405 Result = collections.namedtuple(
'Result_from_build_CcdImage', (
'wcs',
'key',
'filter'))
406 Key = collections.namedtuple(
'Key', (
'visit',
'ccd'))
407 return Result(tanWcs, Key(visit, ccdId), filterName)
412 Jointly calibrate the astrometry and photometry across a set of images. 416 dataRefs : list of lsst.daf.persistence.ButlerDataRef 417 List of data references to the exposures to be fit. 418 profile_jointcal : bool 419 Profile the individual steps of jointcal. 425 * dataRefs: the provided data references that were fit (with updated WCSs) 426 * oldWcsList: the original WCS from each dataRef 427 * metrics: dictionary of internally-computed metrics for testing/validation. 429 if len(dataRefs) == 0:
430 raise ValueError(
'Need a non-empty list of data references!')
434 sourceFluxField =
"slot_%sFlux" % (self.config.sourceFluxType,)
438 visit_ccd_to_dataRef = {}
441 load_cat_prof_file =
'jointcal_build_ccdImage.prof' if profile_jointcal
else '' 442 with pipeBase.cmdLineTask.profile(load_cat_prof_file):
445 camera = dataRefs[0].get(
'camera', immediate=
True)
449 oldWcsList.append(result.wcs)
450 visit_ccd_to_dataRef[result.key] = ref
451 filters.append(result.filter)
452 filters = collections.Counter(filters)
454 associations.computeCommonTangentPoint()
459 bbox = associations.getRaDecBBox()
461 bboxCenter = bbox.getCenter()
462 center = afwGeom.SpherePoint(bboxCenter[0], bboxCenter[1], afwGeom.degrees)
463 bboxMax = bbox.getMax()
464 corner = afwGeom.SpherePoint(bboxMax[0], bboxMax[1], afwGeom.degrees)
465 radius = center.separation(corner).asRadians()
470 raise RuntimeError(
"astrometry_net_data is not setup")
473 defaultFilter = filters.most_common(1)[0][0]
474 self.log.debug(
"Using %s band for reference flux", defaultFilter)
477 tract = dataRefs[0].dataId[
'tract']
479 if self.config.doAstrometry:
482 refObjLoader=self.astrometryRefObjLoader,
484 profile_jointcal=profile_jointcal,
490 if self.config.doPhotometry:
493 refObjLoader=self.photometryRefObjLoader,
495 profile_jointcal=profile_jointcal,
498 reject_bad_fluxes=
True)
503 return pipeBase.Struct(dataRefs=dataRefs,
504 oldWcsList=oldWcsList,
506 exitStatus=exitStatus)
508 def _do_load_refcat_and_fit(self, associations, defaultFilter, center, radius,
509 name="", refObjLoader=None, filters=[], fit_function=None,
510 tract=None, profile_jointcal=False, match_cut=3.0,
511 reject_bad_fluxes=False):
512 """Load reference catalog, perform the fit, and return the result. 516 associations : lsst.jointcal.Associations 517 The star/reference star associations to fit. 519 filter to load from reference catalog. 520 center : lsst.afw.geom.SpherePoint 521 ICRS center of field to load from reference catalog. 522 radius : lsst.afw.geom.Angle 523 On-sky radius to load from reference catalog. 525 Name of thing being fit: "Astrometry" or "Photometry". 526 refObjLoader : lsst.meas.algorithms.LoadReferenceObjectsTask 527 Reference object loader to load from for fit. 528 filters : list of str, optional 529 List of filters to load from the reference catalog. 530 fit_function : function 531 function to call to perform fit (takes associations object). 533 Name of tract currently being fit. 534 profile_jointcal : bool, optional 535 Separately profile the fitting step. 536 match_cut : float, optional 537 Radius in arcseconds to find cross-catalog matches to during 538 associations.associateCatalogs. 539 reject_bad_fluxes : bool, optional 540 Reject refCat sources with NaN/inf flux or NaN/0 fluxErr. 544 Result of `fit_function()` 546 self.log.info(
"====== Now processing %s...", name)
549 associations.associateCatalogs(match_cut)
551 associations.fittedStarListSize())
553 skyCircle = refObjLoader.loadSkyCircle(center,
554 afwGeom.Angle(radius, afwGeom.radians),
558 if not skyCircle.refCat.isContiguous():
559 refCat = skyCircle.refCat.copy(deep=
True)
561 refCat = skyCircle.refCat
568 filtKeys = lsst.meas.algorithms.getRefFluxKeys(refCat.schema, filt)
569 refFluxes[filt] = refCat.get(filtKeys[0])
570 refFluxErrs[filt] = refCat.get(filtKeys[1])
572 associations.collectRefStars(refCat, self.config.matchCut*afwGeom.arcseconds,
573 skyCircle.fluxField, refFluxes, refFluxErrs, reject_bad_fluxes)
575 associations.refStarListSize())
577 associations.prepareFittedStars(self.config.minMeasurements)
581 associations.nFittedStarsWithAssociatedRefStar())
583 associations.fittedStarListSize())
585 associations.nCcdImagesValidForFit())
587 load_cat_prof_file =
'jointcal_fit_%s.prof'%name
if profile_jointcal
else '' 588 dataName =
"{}_{}".format(tract, defaultFilter)
589 with pipeBase.cmdLineTask.profile(load_cat_prof_file):
590 result = fit_function(associations, dataName)
593 if self.config.writeChi2ContributionFiles:
594 baseName =
"{}_final_chi2-{}.csv".format(name, dataName)
595 result.fit.saveChi2Contributions(baseName)
599 def _check_star_lists(self, associations, name):
601 if associations.nCcdImagesValidForFit() == 0:
602 raise RuntimeError(
'No images in the ccdImageList!')
603 if associations.fittedStarListSize() == 0:
604 raise RuntimeError(
'No stars in the {} fittedStarList!'.format(name))
605 if associations.refStarListSize() == 0:
606 raise RuntimeError(
'No stars in the {} reference star list!'.format(name))
608 def _logChi2AndValidate(self, associations, fit, model, chi2Label="Model"):
609 """Compute chi2, log it, validate the model, and return chi2.""" 610 chi2 = fit.computeChi2()
611 self.log.info(
"%s %s", chi2Label, chi2)
613 if not np.isfinite(chi2.chi2):
614 raise FloatingPointError(
'%s chi2 is invalid: %s', chi2Label, chi2)
615 if not model.validate(associations.getCcdImageList()):
616 raise ValueError(
"Model is not valid: check log messages for warnings.")
619 def _fit_photometry(self, associations, dataName=None):
621 Fit the photometric data. 625 associations : lsst.jointcal.Associations 626 The star/reference star associations to fit. 628 Name of the data being processed (e.g. "1234_HSC-Y"), for 629 identifying debugging files. 634 fit : lsst.jointcal.PhotometryFit 635 The photometric fitter used to perform the fit. 636 model : lsst.jointcal.PhotometryModel 637 The photometric model that was fit. 639 self.log.info(
"=== Starting photometric fitting...")
642 if self.config.photometryModel ==
"constrainedFlux":
645 visitOrder=self.config.photometryVisitOrder,
646 errorPedestal=self.config.photometryErrorPedestal)
648 doLineSearch = self.config.allowLineSearch
649 elif self.config.photometryModel ==
"constrainedMagnitude":
652 visitOrder=self.config.photometryVisitOrder,
653 errorPedestal=self.config.photometryErrorPedestal)
655 doLineSearch = self.config.allowLineSearch
656 elif self.config.photometryModel ==
"simpleFlux":
658 errorPedestal=self.config.photometryErrorPedestal)
660 elif self.config.photometryModel ==
"simpleMagnitude":
662 errorPedestal=self.config.photometryErrorPedestal)
670 if self.config.writeChi2ContributionFiles:
671 baseName =
"photometry_initial_chi2-{}.csv".format(dataName)
672 fit.saveChi2Contributions(baseName)
676 dumpMatrixFile =
"photometry_preinit" if self.config.writeInitMatrix
else "" 677 if self.config.photometryModel.startswith(
"constrained"):
680 fit.minimize(
"ModelVisit", dumpMatrixFile=dumpMatrixFile)
684 fit.minimize(
"Model", doLineSearch=doLineSearch, dumpMatrixFile=dumpMatrixFile)
687 fit.minimize(
"Fluxes")
690 fit.minimize(
"Model Fluxes", doLineSearch=doLineSearch)
693 model.freezeErrorTransform()
694 self.log.debug(
"Photometry error scales are frozen.")
698 self.config.maxPhotometrySteps,
701 doRankUpdate=self.config.photometryDoRankUpdate,
702 doLineSearch=doLineSearch,
709 def _fit_astrometry(self, associations, dataName=None):
711 Fit the astrometric data. 715 associations : lsst.jointcal.Associations 716 The star/reference star associations to fit. 718 Name of the data being processed (e.g. "1234_HSC-Y"), for 719 identifying debugging files. 724 fit : lsst.jointcal.AstrometryFit 725 The astrometric fitter used to perform the fit. 726 model : lsst.jointcal.AstrometryModel 727 The astrometric model that was fit. 728 sky_to_tan_projection : lsst.jointcal.ProjectionHandler 729 The model for the sky to tangent plane projection that was used in the fit. 732 self.log.info(
"=== Starting astrometric fitting...")
734 associations.deprojectFittedStars()
741 if self.config.astrometryModel ==
"constrained":
743 sky_to_tan_projection,
744 chipOrder=self.config.astrometryChipOrder,
745 visitOrder=self.config.astrometryVisitOrder)
746 elif self.config.astrometryModel ==
"simple":
748 sky_to_tan_projection,
749 self.config.useInputWcs,
751 order=self.config.astrometrySimpleOrder)
758 if self.config.writeChi2ContributionFiles:
759 baseName =
"astrometry_initial_chi2-{}.csv".format(dataName)
760 fit.saveChi2Contributions(baseName)
762 dumpMatrixFile =
"astrometry_preinit" if self.config.writeInitMatrix
else "" 765 if self.config.astrometryModel ==
"constrained":
766 fit.minimize(
"DistortionsVisit", dumpMatrixFile=dumpMatrixFile)
770 fit.minimize(
"Distortions", dumpMatrixFile=dumpMatrixFile)
773 fit.minimize(
"Positions")
776 fit.minimize(
"Distortions Positions")
781 self.config.maxAstrometrySteps,
783 "Distortions Positions",
784 doRankUpdate=self.config.astrometryDoRankUpdate,
790 return Astrometry(fit, model, sky_to_tan_projection)
792 def _check_stars(self, associations):
793 """Count measured and reference stars per ccd and warn/log them.""" 794 for ccdImage
in associations.getCcdImageList():
795 nMeasuredStars, nRefStars = ccdImage.countStars()
796 self.log.debug(
"ccdImage %s has %s measured and %s reference stars",
797 ccdImage.getName(), nMeasuredStars, nRefStars)
798 if nMeasuredStars < self.config.minMeasuredStarsPerCcd:
799 self.log.warn(
"ccdImage %s has only %s measuredStars (desired %s)",
800 ccdImage.getName(), nMeasuredStars, self.config.minMeasuredStarsPerCcd)
801 if nRefStars < self.config.minRefStarsPerCcd:
802 self.log.warn(
"ccdImage %s has only %s RefStars (desired %s)",
803 ccdImage.getName(), nRefStars, self.config.minRefStarsPerCcd)
805 def _iterate_fit(self, associations, fitter, max_steps, name, whatToFit,
809 """Run fitter.minimize up to max_steps times, returning the final chi2. 813 associations : `lsst.jointcal.Associations` 814 The star/reference star associations to fit. 815 fitter : `lsst.jointcal.FitterBase` 816 The fitter to use for minimization. 818 Maximum number of steps to run outlier rejection before declaring 820 name : {'photometry' or 'astrometry'} 821 What type of data are we fitting (for logs and debugging files). 823 Passed to ``fitter.minimize()`` to define the parameters to fit. 824 dataName : str, optional 825 Descriptive name for this dataset (e.g. tract and filter), 827 doRankUpdate : bool, optional 828 Do an Eigen rank update during minimization, or recompute the full 830 doLineSearch : bool, optional 831 Do a line search for the optimum step during minimization? 835 chi2: `lsst.jointcal.Chi2Statistic` 836 The final chi2 after the fit converges, or is forced to end. 841 Raised if the fitter fails with a non-finite value. 843 Raised if the fitter fails for some other reason; 844 log messages will provide further details. 846 dumpMatrixFile =
"%s_postinit" % name
if self.config.writeInitMatrix
else "" 847 for i
in range(max_steps):
848 result = fitter.minimize(whatToFit,
849 self.config.outlierRejectSigma,
850 doRankUpdate=doRankUpdate,
851 doLineSearch=doLineSearch,
852 dumpMatrixFile=dumpMatrixFile)
856 if result == MinimizeResult.Converged:
858 self.log.debug(
"fit has converged - no more outliers - redo minimization " 859 "one more time in case we have lost accuracy in rank update.")
861 result = fitter.minimize(whatToFit, self.config.outlierRejectSigma)
865 if chi2.chi2/chi2.ndof >= 4.0:
866 self.log.error(
"Potentially bad fit: High chi-squared/ndof.")
869 elif result == MinimizeResult.Chi2Increased:
870 self.log.warn(
"still some outliers but chi2 increases - retry")
871 elif result == MinimizeResult.NonFinite:
872 filename =
"{}_failure-nonfinite_chi2-{}.csv".format(name, dataName)
874 fitter.saveChi2Contributions(filename)
875 msg =
"Nonfinite value in chi2 minimization, cannot complete fit. Dumped star tables to: {}" 876 raise FloatingPointError(msg.format(filename))
877 elif result == MinimizeResult.Failed:
878 raise RuntimeError(
"Chi2 minimization failure, cannot complete fit.")
880 raise RuntimeError(
"Unxepected return code from minimize().")
882 self.log.error(
"%s failed to converge after %d steps"%(name, max_steps))
886 def _write_astrometry_results(self, associations, model, visit_ccd_to_dataRef):
888 Write the fitted astrometric results to a new 'jointcal_wcs' dataRef. 892 associations : lsst.jointcal.Associations 893 The star/reference star associations to fit. 894 model : lsst.jointcal.AstrometryModel 895 The astrometric 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 WCS for visit: %d, ccd: %d", visit, ccd)
907 skyWcs = model.makeSkyWcs(ccdImage)
909 dataRef.put(skyWcs,
'jointcal_wcs')
910 except pexExceptions.Exception
as e:
911 self.log.fatal(
'Failed to write updated Wcs: %s', str(e))
914 def _write_photometry_results(self, associations, model, visit_ccd_to_dataRef):
916 Write the fitted photometric results to a new 'jointcal_photoCalib' dataRef. 920 associations : lsst.jointcal.Associations 921 The star/reference star associations to fit. 922 model : lsst.jointcal.PhotometryModel 923 The photoometric model that was fit. 924 visit_ccd_to_dataRef : dict of Key: lsst.daf.persistence.ButlerDataRef 925 dict of ccdImage identifiers to dataRefs that were fit 928 ccdImageList = associations.getCcdImageList()
929 for ccdImage
in ccdImageList:
932 visit = ccdImage.visit
933 dataRef = visit_ccd_to_dataRef[(visit, ccd)]
934 self.log.info(
"Updating PhotoCalib for visit: %d, ccd: %d", visit, ccd)
935 photoCalib = model.toPhotoCalib(ccdImage)
937 dataRef.put(photoCalib,
'jointcal_photoCalib')
938 except pexExceptions.Exception
as e:
939 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)