24 import astropy.units 
as u
    36 from lsst.verify 
import Job, Measurement
    41 from .dataIds 
import PerTractCcdDataIdContainer
    46 __all__ = [
"JointcalConfig", 
"JointcalRunner", 
"JointcalTask"]
    48 Photometry = collections.namedtuple(
'Photometry', (
'fit', 
'model'))
    49 Astrometry = collections.namedtuple(
'Astrometry', (
'fit', 
'model', 
'sky_to_tan_projection'))
    54     meas = Measurement(job.metrics[name], value)
    55     job.measurements.insert(meas)
    59     """Subclass of TaskRunner for jointcalTask    61     jointcalTask.runDataRef() takes a number of arguments, one of which is a list of dataRefs    62     extracted from the command line (whereas most CmdLineTasks' runDataRef methods take    63     single dataRef, are are called repeatedly). This class transforms the processed    64     arguments generated by the ArgumentParser into the arguments expected by    65     Jointcal.runDataRef().    67     See pipeBase.TaskRunner for more information.    73         Return a list of tuples per tract, each containing (dataRefs, kwargs).    75         Jointcal operates on lists of dataRefs simultaneously.    77         kwargs[
'profile_jointcal'] = parsedCmd.profile_jointcal
    78         kwargs[
'butler'] = parsedCmd.butler
    82         for ref 
in parsedCmd.id.refList:
    83             refListDict.setdefault(ref.dataId[
"tract"], []).
append(ref)
    85         result = [(refListDict[tract], kwargs) 
for tract 
in sorted(refListDict.keys())]
    93             Arguments for Task.runDataRef()    98             if self.doReturnResults is False:   100             - ``exitStatus``: 0 if the task completed successfully, 1 otherwise.   102             if self.doReturnResults is True:   104             - ``result``: the result of calling jointcal.runDataRef()   105             - ``exitStatus``: 0 if the task completed successfully, 1 otherwise.   110         dataRefList, kwargs = args
   111         butler = kwargs.pop(
'butler')
   112         task = self.TaskClass(config=self.config, log=self.log, butler=butler)
   115             result = task.runDataRef(dataRefList, **kwargs)
   116             exitStatus = result.exitStatus
   117             job_path = butler.get(
'verify_job_filename')
   118             result.job.write(job_path[0])
   119         except Exception 
as e:  
   124                 eName = 
type(e).__name__
   125                 tract = dataRefList[0].dataId[
'tract']
   126                 task.log.fatal(
"Failed processing tract %s, %s: %s", tract, eName, e)
   128         if self.doReturnResults:
   129             return pipeBase.Struct(result=result, exitStatus=exitStatus)
   131             return pipeBase.Struct(exitStatus=exitStatus)
   135     """Config for JointcalTask"""   137     doAstrometry = pexConfig.Field(
   138         doc=
"Fit astrometry and write the fitted result.",
   142     doPhotometry = pexConfig.Field(
   143         doc=
"Fit photometry and write the fitted result.",
   147     coaddName = pexConfig.Field(
   148         doc=
"Type of coadd, typically deep or goodSeeing",
   152     positionErrorPedestal = pexConfig.Field(
   153         doc=
"Systematic term to apply to the measured position error (pixels)",
   157     photometryErrorPedestal = pexConfig.Field(
   158         doc=
"Systematic term to apply to the measured error on flux or magnitude as a "   159         "fraction of source flux or magnitude delta (e.g. 0.05 is 5% of flux or +50 millimag).",
   164     matchCut = pexConfig.Field(
   165         doc=
"Matching radius between fitted and reference stars (arcseconds)",
   169     minMeasurements = pexConfig.Field(
   170         doc=
"Minimum number of associated measured stars for a fitted star to be included in the fit",
   174     minMeasuredStarsPerCcd = pexConfig.Field(
   175         doc=
"Minimum number of measuredStars per ccdImage before printing warnings",
   179     minRefStarsPerCcd = pexConfig.Field(
   180         doc=
"Minimum number of measuredStars per ccdImage before printing warnings",
   184     allowLineSearch = pexConfig.Field(
   185         doc=
"Allow a line search during minimization, if it is reasonable for the model"   186         " (models with a significant non-linear component, e.g. constrainedPhotometry).",
   190     astrometrySimpleOrder = pexConfig.Field(
   191         doc=
"Polynomial order for fitting the simple astrometry model.",
   195     astrometryChipOrder = pexConfig.Field(
   196         doc=
"Order of the per-chip transform for the constrained astrometry model.",
   200     astrometryVisitOrder = pexConfig.Field(
   201         doc=
"Order of the per-visit transform for the constrained astrometry model.",
   205     useInputWcs = pexConfig.Field(
   206         doc=
"Use the input calexp WCSs to initialize a SimpleAstrometryModel.",
   210     astrometryModel = pexConfig.ChoiceField(
   211         doc=
"Type of model to fit to astrometry",
   213         default=
"constrained",
   214         allowed={
"simple": 
"One polynomial per ccd",
   215                  "constrained": 
"One polynomial per ccd, and one polynomial per visit"}
   217     photometryModel = pexConfig.ChoiceField(
   218         doc=
"Type of model to fit to photometry",
   220         default=
"constrainedMagnitude",
   221         allowed={
"simpleFlux": 
"One constant zeropoint per ccd and visit, fitting in flux space.",
   222                  "constrainedFlux": 
"Constrained zeropoint per ccd, and one polynomial per visit,"   223                  " fitting in flux space.",
   224                  "simpleMagnitude": 
"One constant zeropoint per ccd and visit,"   225                  " fitting in magnitude space.",
   226                  "constrainedMagnitude": 
"Constrained zeropoint per ccd, and one polynomial per visit,"   227                  " fitting in magnitude space.",
   230     applyColorTerms = pexConfig.Field(
   231         doc=
"Apply photometric color terms to reference stars?"   232             "Requires that colorterms be set to a ColortermLibrary",
   236     colorterms = pexConfig.ConfigField(
   237         doc=
"Library of photometric reference catalog name to color term dict.",
   238         dtype=ColortermLibrary,
   240     photometryVisitOrder = pexConfig.Field(
   241         doc=
"Order of the per-visit polynomial transform for the constrained photometry model.",
   245     photometryDoRankUpdate = pexConfig.Field(
   246         doc=
"Do the rank update step during minimization. "   247         "Skipping this can help deal with models that are too non-linear.",
   251     astrometryDoRankUpdate = pexConfig.Field(
   252         doc=
"Do the rank update step during minimization (should not change the astrometry fit). "   253         "Skipping this can help deal with models that are too non-linear.",
   257     outlierRejectSigma = pexConfig.Field(
   258         doc=
"How many sigma to reject outliers at during minimization.",
   262     maxPhotometrySteps = pexConfig.Field(
   263         doc=
"Maximum number of minimize iterations to take when fitting photometry.",
   267     maxAstrometrySteps = pexConfig.Field(
   268         doc=
"Maximum number of minimize iterations to take when fitting photometry.",
   272     astrometryRefObjLoader = pexConfig.ConfigurableField(
   273         target=LoadIndexedReferenceObjectsTask,
   274         doc=
"Reference object loader for astrometric fit",
   276     photometryRefObjLoader = pexConfig.ConfigurableField(
   277         target=LoadIndexedReferenceObjectsTask,
   278         doc=
"Reference object loader for photometric fit",
   280     sourceSelector = sourceSelectorRegistry.makeField(
   281         doc=
"How to select sources for cross-matching",
   284     writeInitMatrix = pexConfig.Field(
   286         doc=
"Write the pre/post-initialization Hessian and gradient to text files, for debugging."   287             "The output files will be of the form 'astrometry_preinit-mat.txt', in the current directory."   288             "Note that these files are the dense versions of the matrix, and so may be very large.",
   291     writeChi2ContributionFiles = pexConfig.Field(
   293         doc=
"Write initial/final fit files containing the contributions to chi2.",
   296     sourceFluxType = pexConfig.Field(
   298         doc=
"Source flux field to use in source selection and to get fluxes from the catalog.",
   305             msg = 
"applyColorTerms=True requires the `colorterms` field be set to a ColortermLibrary."   306             raise pexConfig.FieldValidationError(JointcalConfig.colorterms, self, msg)
   310         sourceSelector.setDefaults()
   312         sourceSelector.badFlags.extend([
"slot_Shape_flag"])
   318     """Jointly astrometrically and photometrically calibrate a group of images."""   320     ConfigClass = JointcalConfig
   321     RunnerClass = JointcalRunner
   322     _DefaultName = 
"jointcal"   324     def __init__(self, butler=None, profile_jointcal=False, **kwargs):
   326         Instantiate a JointcalTask.   330         butler : lsst.daf.persistence.Butler   331             The butler is passed to the refObjLoader constructor in case it is   332             needed. Ignored if the refObjLoader argument provides a loader directly.   333             Used to initialize the astrometry and photometry refObjLoaders.   334         profile_jointcal : bool   335             set to True to profile different stages of this jointcal run.   337         pipeBase.CmdLineTask.__init__(self, **kwargs)
   339         self.makeSubtask(
"sourceSelector")
   340         if self.config.doAstrometry:
   341             self.makeSubtask(
'astrometryRefObjLoader', butler=butler)
   344         if self.config.doPhotometry:
   345             self.makeSubtask(
'photometryRefObjLoader', butler=butler)
   350         self.
job = Job.load_metrics_package(subset=
'jointcal')
   354     def _getConfigName(self):
   357     def _getMetadataName(self):
   361     def _makeArgumentParser(cls):
   362         """Create an argument parser"""   364         parser.add_argument(
"--profile_jointcal", default=
False, action=
"store_true",
   365                             help=
"Profile steps of jointcal separately.")
   366         parser.add_id_argument(
"--id", 
"calexp", help=
"data ID, e.g. --id visit=6789 ccd=0..9",
   367                                ContainerClass=PerTractCcdDataIdContainer)
   370     def _build_ccdImage(self, dataRef, associations, jointcalControl):
   372         Extract the necessary things from this dataRef to add a new ccdImage.   376         dataRef : lsst.daf.persistence.ButlerDataRef   377             dataRef to extract info from.   378         associations : lsst.jointcal.Associations   379             object to add the info to, to construct a new CcdImage   380         jointcalControl : jointcal.JointcalControl   381             control object for associations management   386             wcs : lsst.afw.geom.SkyWcs   387                 the TAN WCS of this image, read from the calexp   389                 a key to identify this dataRef by its visit and ccd ids   393         if "visit" in dataRef.dataId.keys():
   394             visit = dataRef.dataId[
"visit"]
   396             visit = dataRef.getButler().queryMetadata(
"calexp", (
"visit"), dataRef.dataId)[0]
   398         src = dataRef.get(
"src", flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS, immediate=
True)
   400         visitInfo = dataRef.get(
'calexp_visitInfo')
   401         detector = dataRef.get(
'calexp_detector')
   402         ccdId = detector.getId()
   403         calib = dataRef.get(
'calexp_calib')
   404         tanWcs = dataRef.get(
'calexp_wcs')
   405         bbox = dataRef.get(
'calexp_bbox')
   406         filt = dataRef.get(
'calexp_filter')
   407         filterName = filt.getName()
   408         fluxMag0 = calib.getFluxMag0()
   410         referenceFlux = 1e23 * 10**(48.6 / -2.5) * 1e9
   412                                          referenceFlux*fluxMag0[1]/fluxMag0[0]**2, bbox)
   414         goodSrc = self.sourceSelector.
run(src)
   416         if len(goodSrc.sourceCat) == 0:
   417             self.log.
warn(
"No sources selected in visit %s ccd %s", visit, ccdId)
   419             self.log.
info(
"%d sources selected in visit %d ccd %d", len(goodSrc.sourceCat), visit, ccdId)
   420         associations.createCcdImage(goodSrc.sourceCat,
   431         Result = collections.namedtuple(
'Result_from_build_CcdImage', (
'wcs', 
'key', 
'filter'))
   432         Key = collections.namedtuple(
'Key', (
'visit', 
'ccd'))
   433         return Result(tanWcs, Key(visit, ccdId), filterName)
   438         Jointly calibrate the astrometry and photometry across a set of images.   442         dataRefs : list of lsst.daf.persistence.ButlerDataRef   443             List of data references to the exposures to be fit.   444         profile_jointcal : bool   445             Profile the individual steps of jointcal.   451             * dataRefs: the provided data references that were fit (with updated WCSs)   452             * oldWcsList: the original WCS from each dataRef   453             * metrics: dictionary of internally-computed metrics for testing/validation.   455         if len(dataRefs) == 0:
   456             raise ValueError(
'Need a non-empty list of data references!')
   460         sourceFluxField = 
"slot_%sFlux" % (self.config.sourceFluxType,)
   464         visit_ccd_to_dataRef = {}
   467         load_cat_prof_file = 
'jointcal_build_ccdImage.prof' if profile_jointcal 
else ''   468         with pipeBase.cmdLineTask.profile(load_cat_prof_file):
   471             camera = dataRefs[0].get(
'camera', immediate=
True)
   475                 oldWcsList.append(result.wcs)
   476                 visit_ccd_to_dataRef[result.key] = ref
   477                 filters.append(result.filter)
   478         filters = collections.Counter(filters)
   480         associations.computeCommonTangentPoint()
   485         bbox = associations.getRaDecBBox()
   486         bboxCenter = bbox.getCenter()
   488         bboxMax = bbox.getMax()
   490         radius = center.separation(corner).asRadians()
   495             raise RuntimeError(
"astrometry_net_data is not setup")
   498         defaultFilter = filters.most_common(1)[0][0]
   499         self.log.
debug(
"Using %s band for reference flux", defaultFilter)
   502         tract = dataRefs[0].dataId[
'tract']
   504         if self.config.doAstrometry:
   509                                                       profile_jointcal=profile_jointcal,
   515         if self.config.doPhotometry:
   520                                                       profile_jointcal=profile_jointcal,
   523                                                       reject_bad_fluxes=
True)
   528         return pipeBase.Struct(dataRefs=dataRefs,
   529                                oldWcsList=oldWcsList,
   533                                defaultFilter=defaultFilter,
   534                                exitStatus=exitStatus)
   536     def _do_load_refcat_and_fit(self, associations, defaultFilter, center, radius,
   537                                 name="", refObjLoader=None, filters=[], fit_function=None,
   538                                 tract=None, profile_jointcal=False, match_cut=3.0,
   539                                 reject_bad_fluxes=False):
   540         """Load reference catalog, perform the fit, and return the result.   544         associations : lsst.jointcal.Associations   545             The star/reference star associations to fit.   547             filter to load from reference catalog.   548         center : lsst.afw.geom.SpherePoint   549             ICRS center of field to load from reference catalog.   550         radius : lsst.afw.geom.Angle   551             On-sky radius to load from reference catalog.   553             Name of thing being fit: "Astrometry" or "Photometry".   554         refObjLoader : lsst.meas.algorithms.LoadReferenceObjectsTask   555             Reference object loader to load from for fit.   556         filters : list of str, optional   557             List of filters to load from the reference catalog.   558         fit_function : function   559             function to call to perform fit (takes associations object).   561             Name of tract currently being fit.   562         profile_jointcal : bool, optional   563             Separately profile the fitting step.   564         match_cut : float, optional   565             Radius in arcseconds to find cross-catalog matches to during   566             associations.associateCatalogs.   567         reject_bad_fluxes : bool, optional   568             Reject refCat sources with NaN/inf flux or NaN/0 fluxErr.   572         Result of `fit_function()`   574         self.log.
info(
"====== Now processing %s...", name)
   577         associations.associateCatalogs(match_cut)
   579                         associations.fittedStarListSize())
   581         applyColorterms = 
False if name == 
"Astrometry" else self.config.applyColorTerms
   583                                                          applyColorterms=applyColorterms)
   585         associations.collectRefStars(refCat, self.config.matchCut*afwGeom.arcseconds,
   586                                      fluxField, reject_bad_fluxes)
   588                         associations.refStarListSize())
   590         associations.prepareFittedStars(self.config.minMeasurements)
   594                         associations.nFittedStarsWithAssociatedRefStar())
   596                         associations.fittedStarListSize())
   598                         associations.nCcdImagesValidForFit())
   600         load_cat_prof_file = 
'jointcal_fit_%s.prof'%name 
if profile_jointcal 
else ''   601         dataName = 
"{}_{}".
format(tract, defaultFilter)
   602         with pipeBase.cmdLineTask.profile(load_cat_prof_file):
   603             result = fit_function(associations, dataName)
   606         if self.config.writeChi2ContributionFiles:
   607             baseName = 
"{}_final_chi2-{}.csv".
format(name, dataName)
   608             result.fit.saveChi2Contributions(baseName)
   612     def _load_reference_catalog(self, refObjLoader, center, radius, filterName,
   613                                 applyColorterms=False):
   614         """Load the necessary reference catalog sources, convert fluxes to   615         correct units, and apply color term corrections if requested.   619         refObjLoader : `lsst.meas.algorithms.LoadReferenceObjectsTask`   620             The reference catalog loader to use to get the data.   621         center : `lsst.geom.SpherePoint`   622             The center around which to load sources.   623         radius : `lsst.geom.Angle`   624             The radius around ``center`` to load sources in.   626             The name of the camera filter to load fluxes for.   627         applyColorterms : `bool`   628             Apply colorterm corrections to the refcat for ``filterName``?   632         refCat : `lsst.afw.table.SimpleCatalog`   633             The loaded reference catalog.   635             The name of the reference catalog flux field appropriate for ``filterName``.   637         skyCircle = refObjLoader.loadSkyCircle(center,
   642         if not skyCircle.refCat.isContiguous():
   643             refCat = skyCircle.refCat.copy(deep=
True)
   645             refCat = skyCircle.refCat
   649                 refCatName = refObjLoader.ref_dataset_name
   650             except AttributeError:
   652                 raise RuntimeError(
"Cannot perform colorterm corrections with a.net refcats.")
   653             self.log.
info(
"Applying color terms for filterName=%r reference catalog=%s",
   654                           filterName, refCatName)
   655             colorterm = self.config.colorterms.getColorterm(
   656                 filterName=filterName, photoCatName=refCatName, doRaise=
True)
   658             refMag, refMagErr = colorterm.getCorrectedMagnitudes(refCat, filterName)
   659             refCat[skyCircle.fluxField] = u.Magnitude(refMag, u.ABmag).to_value(u.nJy)
   664             refCat[skyCircle.fluxField] *= 1e9
   666                 refCat[skyCircle.fluxField+
'Err'] *= 1e9
   671         return refCat, skyCircle.fluxField
   673     def _check_star_lists(self, associations, name):
   675         if associations.nCcdImagesValidForFit() == 0:
   676             raise RuntimeError(
'No images in the ccdImageList!')
   677         if associations.fittedStarListSize() == 0:
   678             raise RuntimeError(
'No stars in the {} fittedStarList!'.
format(name))
   679         if associations.refStarListSize() == 0:
   680             raise RuntimeError(
'No stars in the {} reference star list!'.
format(name))
   682     def _logChi2AndValidate(self, associations, fit, model, chi2Label="Model"):
   683         """Compute chi2, log it, validate the model, and return chi2."""   684         chi2 = fit.computeChi2()
   685         self.log.
info(
"%s %s", chi2Label, chi2)
   687         if not np.isfinite(chi2.chi2):
   688             raise FloatingPointError(
'%s chi2 is invalid: %s', chi2Label, chi2)
   689         if not model.validate(associations.getCcdImageList()):
   690             raise ValueError(
"Model is not valid: check log messages for warnings.")
   693     def _fit_photometry(self, associations, dataName=None):
   695         Fit the photometric data.   699         associations : lsst.jointcal.Associations   700             The star/reference star associations to fit.   702             Name of the data being processed (e.g. "1234_HSC-Y"), for   703             identifying debugging files.   708             fit : lsst.jointcal.PhotometryFit   709                 The photometric fitter used to perform the fit.   710             model : lsst.jointcal.PhotometryModel   711                 The photometric model that was fit.   713         self.log.
info(
"=== Starting photometric fitting...")
   716         if self.config.photometryModel == 
"constrainedFlux":
   719                                                        visitOrder=self.config.photometryVisitOrder,
   720                                                        errorPedestal=self.config.photometryErrorPedestal)
   722             doLineSearch = self.config.allowLineSearch
   723         elif self.config.photometryModel == 
"constrainedMagnitude":
   726                                                             visitOrder=self.config.photometryVisitOrder,
   727                                                             errorPedestal=self.config.photometryErrorPedestal)
   729             doLineSearch = self.config.allowLineSearch
   730         elif self.config.photometryModel == 
"simpleFlux":
   732                                                   errorPedestal=self.config.photometryErrorPedestal)
   734         elif self.config.photometryModel == 
"simpleMagnitude":
   736                                                        errorPedestal=self.config.photometryErrorPedestal)
   744         if self.config.writeChi2ContributionFiles:
   745             baseName = 
"photometry_initial_chi2-{}.csv".
format(dataName)
   746             fit.saveChi2Contributions(baseName)
   750         dumpMatrixFile = 
"photometry_preinit" if self.config.writeInitMatrix 
else ""   751         if self.config.photometryModel.startswith(
"constrained"):
   754             fit.minimize(
"ModelVisit", dumpMatrixFile=dumpMatrixFile)
   758         fit.minimize(
"Model", doLineSearch=doLineSearch, dumpMatrixFile=dumpMatrixFile)
   761         fit.minimize(
"Fluxes")  
   764         fit.minimize(
"Model Fluxes", doLineSearch=doLineSearch)
   767         model.freezeErrorTransform()
   768         self.log.
debug(
"Photometry error scales are frozen.")
   772                                  self.config.maxPhotometrySteps,
   775                                  doRankUpdate=self.config.photometryDoRankUpdate,
   776                                  doLineSearch=doLineSearch,
   783     def _fit_astrometry(self, associations, dataName=None):
   785         Fit the astrometric data.   789         associations : lsst.jointcal.Associations   790             The star/reference star associations to fit.   792             Name of the data being processed (e.g. "1234_HSC-Y"), for   793             identifying debugging files.   798             fit : lsst.jointcal.AstrometryFit   799                 The astrometric fitter used to perform the fit.   800             model : lsst.jointcal.AstrometryModel   801                 The astrometric model that was fit.   802             sky_to_tan_projection : lsst.jointcal.ProjectionHandler   803                 The model for the sky to tangent plane projection that was used in the fit.   806         self.log.
info(
"=== Starting astrometric fitting...")
   808         associations.deprojectFittedStars()
   815         if self.config.astrometryModel == 
"constrained":
   817                                                              sky_to_tan_projection,
   818                                                              chipOrder=self.config.astrometryChipOrder,
   819                                                              visitOrder=self.config.astrometryVisitOrder)
   820         elif self.config.astrometryModel == 
"simple":
   822                                                         sky_to_tan_projection,
   823                                                         self.config.useInputWcs,
   825                                                         order=self.config.astrometrySimpleOrder)
   832         if self.config.writeChi2ContributionFiles:
   833             baseName = 
"astrometry_initial_chi2-{}.csv".
format(dataName)
   834             fit.saveChi2Contributions(baseName)
   836         dumpMatrixFile = 
"astrometry_preinit" if self.config.writeInitMatrix 
else ""   839         if self.config.astrometryModel == 
"constrained":
   840             fit.minimize(
"DistortionsVisit", dumpMatrixFile=dumpMatrixFile)
   844         fit.minimize(
"Distortions", dumpMatrixFile=dumpMatrixFile)
   847         fit.minimize(
"Positions")
   850         fit.minimize(
"Distortions Positions")
   855                                  self.config.maxAstrometrySteps,
   857                                  "Distortions Positions",
   858                                  doRankUpdate=self.config.astrometryDoRankUpdate,
   864         return Astrometry(fit, model, sky_to_tan_projection)
   866     def _check_stars(self, associations):
   867         """Count measured and reference stars per ccd and warn/log them."""   868         for ccdImage 
in associations.getCcdImageList():
   869             nMeasuredStars, nRefStars = ccdImage.countStars()
   870             self.log.
debug(
"ccdImage %s has %s measured and %s reference stars",
   871                            ccdImage.getName(), nMeasuredStars, nRefStars)
   872             if nMeasuredStars < self.config.minMeasuredStarsPerCcd:
   873                 self.log.
warn(
"ccdImage %s has only %s measuredStars (desired %s)",
   874                               ccdImage.getName(), nMeasuredStars, self.config.minMeasuredStarsPerCcd)
   875             if nRefStars < self.config.minRefStarsPerCcd:
   876                 self.log.
warn(
"ccdImage %s has only %s RefStars (desired %s)",
   877                               ccdImage.getName(), nRefStars, self.config.minRefStarsPerCcd)
   879     def _iterate_fit(self, associations, fitter, max_steps, name, whatToFit,
   883         """Run fitter.minimize up to max_steps times, returning the final chi2.   887         associations : `lsst.jointcal.Associations`   888             The star/reference star associations to fit.   889         fitter : `lsst.jointcal.FitterBase`   890             The fitter to use for minimization.   892             Maximum number of steps to run outlier rejection before declaring   894         name : {'photometry' or 'astrometry'}   895             What type of data are we fitting (for logs and debugging files).   897             Passed to ``fitter.minimize()`` to define the parameters to fit.   898         dataName : str, optional   899             Descriptive name for this dataset (e.g. tract and filter),   901         doRankUpdate : bool, optional   902             Do an Eigen rank update during minimization, or recompute the full   904         doLineSearch : bool, optional   905             Do a line search for the optimum step during minimization?   909         chi2: `lsst.jointcal.Chi2Statistic`   910             The final chi2 after the fit converges, or is forced to end.   915             Raised if the fitter fails with a non-finite value.   917             Raised if the fitter fails for some other reason;   918             log messages will provide further details.   920         dumpMatrixFile = 
"%s_postinit" % name 
if self.config.writeInitMatrix 
else ""   921         for i 
in range(max_steps):
   922             result = fitter.minimize(whatToFit,
   923                                      self.config.outlierRejectSigma,
   924                                      doRankUpdate=doRankUpdate,
   925                                      doLineSearch=doLineSearch,
   926                                      dumpMatrixFile=dumpMatrixFile)
   930             if result == MinimizeResult.Converged:
   932                     self.log.
debug(
"fit has converged - no more outliers - redo minimization "   933                                    "one more time in case we have lost accuracy in rank update.")
   935                     result = fitter.minimize(whatToFit, self.config.outlierRejectSigma)
   939                 if chi2.chi2/chi2.ndof >= 4.0:
   940                     self.log.
error(
"Potentially bad fit: High chi-squared/ndof.")
   943             elif result == MinimizeResult.Chi2Increased:
   944                 self.log.
warn(
"still some outliers but chi2 increases - retry")
   945             elif result == MinimizeResult.NonFinite:
   946                 filename = 
"{}_failure-nonfinite_chi2-{}.csv".
format(name, dataName)
   948                 fitter.saveChi2Contributions(filename)
   949                 msg = 
"Nonfinite value in chi2 minimization, cannot complete fit. Dumped star tables to: {}"   950                 raise FloatingPointError(msg.format(filename))
   951             elif result == MinimizeResult.Failed:
   952                 raise RuntimeError(
"Chi2 minimization failure, cannot complete fit.")
   954                 raise RuntimeError(
"Unxepected return code from minimize().")
   956             self.log.
error(
"%s failed to converge after %d steps"%(name, max_steps))
   960     def _write_astrometry_results(self, associations, model, visit_ccd_to_dataRef):
   962         Write the fitted astrometric results to a new 'jointcal_wcs' dataRef.   966         associations : lsst.jointcal.Associations   967             The star/reference star associations to fit.   968         model : lsst.jointcal.AstrometryModel   969             The astrometric model that was fit.   970         visit_ccd_to_dataRef : dict of Key: lsst.daf.persistence.ButlerDataRef   971             dict of ccdImage identifiers to dataRefs that were fit   974         ccdImageList = associations.getCcdImageList()
   975         for ccdImage 
in ccdImageList:
   978             visit = ccdImage.visit
   979             dataRef = visit_ccd_to_dataRef[(visit, ccd)]
   980             self.log.
info(
"Updating WCS for visit: %d, ccd: %d", visit, ccd)
   981             skyWcs = model.makeSkyWcs(ccdImage)
   983                 dataRef.put(skyWcs, 
'jointcal_wcs')
   985                 self.log.
fatal(
'Failed to write updated Wcs: %s', 
str(e))
   988     def _write_photometry_results(self, associations, model, visit_ccd_to_dataRef):
   990         Write the fitted photometric results to a new 'jointcal_photoCalib' dataRef.   994         associations : lsst.jointcal.Associations   995             The star/reference star associations to fit.   996         model : lsst.jointcal.PhotometryModel   997             The photoometric model that was fit.   998         visit_ccd_to_dataRef : dict of Key: lsst.daf.persistence.ButlerDataRef   999             dict of ccdImage identifiers to dataRefs that were fit  1002         ccdImageList = associations.getCcdImageList()
  1003         for ccdImage 
in ccdImageList:
  1005             ccd = ccdImage.ccdId
  1006             visit = ccdImage.visit
  1007             dataRef = visit_ccd_to_dataRef[(visit, ccd)]
  1008             self.log.
info(
"Updating PhotoCalib for visit: %d, ccd: %d", visit, ccd)
  1009             photoCalib = model.toPhotoCalib(ccdImage)
  1011                 dataRef.put(photoCalib, 
'jointcal_photoCalib')
  1013                 self.log.
fatal(
'Failed to write updated PhotoCalib: %s', 
str(e))
 
def runDataRef(self, dataRefs, profile_jointcal=False)
double fluxErrFromABMagErr(double magErr, double mag) noexcept
Compute flux error in Janskys from AB magnitude error and AB magnitude. 
def _build_ccdImage(self, dataRef, associations, jointcalControl)
def _fit_photometry(self, associations, dataName=None)
The photometric calibration of an exposure. 
def getTargetList(parsedCmd, kwargs)
def _fit_astrometry(self, associations, dataName=None)
Provides consistent interface for LSST exceptions. 
std::shared_ptr< FrameSet > append(FrameSet const &first, FrameSet const &second)
Construct a FrameSet that performs two transformations in series. 
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
def _check_star_lists(self, associations, name)
def _load_reference_catalog(self, refObjLoader, center, radius, filterName, applyColorterms=False)
The class that implements the relations between MeasuredStar and FittedStar. 
A class representing an angle. 
A projection handler in which all CCDs from the same visit have the same tangent point. 
std::string getPackageDir(std::string const &packageName)
return the root directory of a setup package 
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 format(config, name=None, writeSourceLine=True, prefix="", verbose=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. 
Point in an unspecified spherical coordinate system. 
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)