lsst.jointcal  master-ga8493ae4fe+3
jointcal.py
Go to the documentation of this file.
1 # See COPYRIGHT file at the top of the source tree.
2 
3 from __future__ import division, absolute_import, print_function
4 from builtins import str
5 from builtins import range
6 
7 import collections
8 
9 import lsst.utils
10 import lsst.pex.config as pexConfig
11 import lsst.pipe.base as pipeBase
12 import lsst.afw.image as afwImage
13 import lsst.afw.geom as afwGeom
14 import lsst.afw.coord as afwCoord
15 import lsst.pex.exceptions as pexExceptions
16 import lsst.afw.table
17 import lsst.meas.algorithms
18 
19 from lsst.meas.extensions.astrometryNet import LoadAstrometryNetObjectsTask
20 from lsst.meas.algorithms.sourceSelector import sourceSelectorRegistry
21 
22 from .dataIds import PerTractCcdDataIdContainer
23 
24 import lsst.jointcal
25 from lsst.jointcal import MinimizeResult
26 
27 __all__ = ["JointcalConfig", "JointcalTask"]
28 
29 Photometry = collections.namedtuple('Photometry', ('fit', 'model'))
30 Astrometry = collections.namedtuple('Astrometry', ('fit', 'model', 'sky_to_tan_projection'))
31 
32 
33 class JointcalRunner(pipeBase.ButlerInitializedTaskRunner):
34  """Subclass of TaskRunner for jointcalTask
35 
36  jointcalTask.run() takes a number of arguments, one of which is a list of dataRefs
37  extracted from the command line (whereas most CmdLineTasks' run methods take
38  single dataRef, are are called repeatedly). This class transforms the processed
39  arguments generated by the ArgumentParser into the arguments expected by
40  Jointcal.run().
41 
42  See pipeBase.TaskRunner for more information.
43  """
44 
45  @staticmethod
46  def getTargetList(parsedCmd, **kwargs):
47  """
48  Return a list of tuples per tract, each containing (dataRefs, kwargs).
49 
50  Jointcal operates on lists of dataRefs simultaneously.
51  """
52  kwargs['profile_jointcal'] = parsedCmd.profile_jointcal
53  kwargs['butler'] = parsedCmd.butler
54 
55  # organize data IDs by tract
56  refListDict = {}
57  for ref in parsedCmd.id.refList:
58  refListDict.setdefault(ref.dataId["tract"], []).append(ref)
59  # we call run() once with each tract
60  result = [(refListDict[tract], kwargs) for tract in sorted(refListDict.keys())]
61  return result
62 
63  def __call__(self, args):
64  """
65  @param args Arguments for Task.run()
66 
67  @return
68  - None if self.doReturnResults is False
69  - A pipe.base.Struct containing these fields if self.doReturnResults is True:
70  - dataRef: the provided data references, with update post-fit WCS's.
71  """
72  # NOTE: cannot call self.makeTask because that assumes args[0] is a single dataRef.
73  dataRefList, kwargs = args
74  butler = kwargs.pop('butler')
75  task = self.TaskClass(config=self.config, log=self.log, butler=butler)
76  result = task.run(dataRefList, **kwargs)
77  if self.doReturnResults:
78  return pipeBase.Struct(result=result)
79 
80 
81 class JointcalConfig(pexConfig.Config):
82  """Config for jointcalTask"""
83 
84  doAstrometry = pexConfig.Field(
85  doc="Fit astrometry and write the fitted result.",
86  dtype=bool,
87  default=True
88  )
89  doPhotometry = pexConfig.Field(
90  doc="Fit photometry and write the fitted result.",
91  dtype=bool,
92  default=True
93  )
94  coaddName = pexConfig.Field(
95  doc="Type of coadd, typically deep or goodSeeing",
96  dtype=str,
97  default="deep"
98  )
99  posError = pexConfig.Field(
100  doc="Constant term for error on position (in pixel unit)",
101  dtype=float,
102  default=0.02,
103  )
104  # TODO: DM-6885 matchCut should be an afw.geom.Angle
105  matchCut = pexConfig.Field(
106  doc="Matching radius between fitted and reference stars (arcseconds)",
107  dtype=float,
108  default=3.0,
109  )
110  minMeasurements = pexConfig.Field(
111  doc="Minimum number of associated measured stars for a fitted star to be included in the fit",
112  dtype=int,
113  default=2,
114  )
115  polyOrder = pexConfig.Field(
116  doc="Polynomial order for fitting distorsion",
117  dtype=int,
118  default=3,
119  )
120  astrometryModel = pexConfig.ChoiceField(
121  doc="Type of model to fit to astrometry",
122  dtype=str,
123  default="simplePoly",
124  allowed={"simplePoly": "One polynomial per ccd",
125  "constrainedPoly": "One polynomial per ccd, and one polynomial per visit"}
126  )
127  photometryModel = pexConfig.ChoiceField(
128  doc="Type of model to fit to photometry",
129  dtype=str,
130  default="simple",
131  allowed={"simple": "One constant zeropoint per ccd and visit",
132  "constrained": "Constrained zeropoint per ccd, and one polynomial per visit"}
133  )
134  astrometryRefObjLoader = pexConfig.ConfigurableField(
135  target=LoadAstrometryNetObjectsTask,
136  doc="Reference object loader for astrometric fit",
137  )
138  photometryRefObjLoader = pexConfig.ConfigurableField(
139  target=LoadAstrometryNetObjectsTask,
140  doc="Reference object loader for photometric fit",
141  )
142  sourceSelector = sourceSelectorRegistry.makeField(
143  doc="How to select sources for cross-matching",
144  default="astrometry"
145  )
146 
147  def setDefaults(self):
148  sourceSelector = self.sourceSelector["astrometry"]
149  sourceSelector.setDefaults()
150  # don't want to lose existing flags, just add to them.
151  sourceSelector.badFlags.extend(["slot_Shape_flag"])
152  # This should be used to set the FluxField value in jointcal::JointcalControl
153  sourceSelector.sourceFluxType = 'Calib'
154 
155 
156 class JointcalTask(pipeBase.CmdLineTask):
157  """Jointly astrometrically (photometrically later) calibrate a group of images."""
158 
159  ConfigClass = JointcalConfig
160  RunnerClass = JointcalRunner
161  _DefaultName = "jointcal"
162 
163  def __init__(self, butler=None, profile_jointcal=False, **kwargs):
164  """
165  Instantiate a JointcalTask.
166 
167  Parameters
168  ----------
169  butler : lsst.daf.persistence.Butler
170  The butler is passed to the refObjLoader constructor in case it is
171  needed. Ignored if the refObjLoader argument provides a loader directly.
172  Used to initialize the astrometry and photometry refObjLoaders.
173  profile_jointcal : bool
174  set to True to profile different stages of this jointcal run.
175  """
176  pipeBase.CmdLineTask.__init__(self, **kwargs)
177  self.profile_jointcal = profile_jointcal
178  self.makeSubtask("sourceSelector")
179  self.makeSubtask('astrometryRefObjLoader', butler=butler)
180  self.makeSubtask('photometryRefObjLoader', butler=butler)
181 
182  # To hold various computed metrics for use by tests
183  self.metrics = {}
184 
185  # We don't need to persist config and metadata at this stage.
186  # In this way, we don't need to put a specific entry in the camera mapper policy file
187  def _getConfigName(self):
188  return None
189 
190  def _getMetadataName(self):
191  return None
192 
193  @classmethod
194  def _makeArgumentParser(cls):
195  """Create an argument parser"""
196  parser = pipeBase.ArgumentParser(name=cls._DefaultName)
197  parser.add_argument("--profile_jointcal", default=False, action="store_true",
198  help="Profile steps of jointcal separately.")
199  parser.add_id_argument("--id", "calexp", help="data ID, e.g. --id visit=6789 ccd=0..9",
200  ContainerClass=PerTractCcdDataIdContainer)
201  return parser
202 
203  def _build_ccdImage(self, dataRef, associations, jointcalControl):
204  """
205  Extract the necessary things from this dataRef to add a new ccdImage.
206 
207  Parameters
208  ----------
209  dataRef : lsst.daf.persistence.ButlerDataRef
210  dataRef to extract info from.
211  associations : lsst.jointcal.Associations
212  object to add the info to, to construct a new CcdImage
213  jointcalControl : jointcal.JointcalControl
214  control object for associations management
215 
216  Returns
217  ------
218  namedtuple
219  wcs : lsst.afw.image.TanWcs
220  the TAN WCS of this image, read from the calexp
221  key : namedtuple
222  a key to identify this dataRef by its visit and ccd ids
223  filter : str
224  this calexp's filter
225  """
226  if "visit" in dataRef.dataId.keys():
227  visit = dataRef.dataId["visit"]
228  else:
229  visit = dataRef.getButler().queryMetadata("calexp", ("visit"), dataRef.dataId)[0]
230  src = dataRef.get("src", flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS, immediate=True)
231  calexp = dataRef.get("calexp", immediate=True)
232  visitInfo = calexp.getInfo().getVisitInfo()
233  ccdname = calexp.getDetector().getId()
234 
235  calib = calexp.getCalib()
236  tanWcs = calexp.getWcs()
237  bbox = calexp.getBBox()
238  filt = calexp.getInfo().getFilter().getName()
239  fluxMag0 = calib.getFluxMag0()
240  photoCalib = afwImage.PhotoCalib(fluxMag0[0], fluxMag0[1], bbox)
241 
242  goodSrc = self.sourceSelector.selectSources(src)
243 
244  if len(goodSrc.sourceCat) == 0:
245  self.log.warn("no stars selected in ", visit, ccdname)
246  return tanWcs
247  self.log.info("%d stars selected in visit %d ccd %d", len(goodSrc.sourceCat), visit, ccdname)
248  associations.addImage(goodSrc.sourceCat, tanWcs, visitInfo, bbox, filt, photoCalib,
249  visit, ccdname, jointcalControl)
250 
251  Result = collections.namedtuple('Result_from_build_CcdImage', ('wcs', 'key', 'filter'))
252  Key = collections.namedtuple('Key', ('visit', 'ccd'))
253  return Result(tanWcs, Key(visit, ccdname), filt)
254 
255  @pipeBase.timeMethod
256  def run(self, dataRefs, profile_jointcal=False):
257  """
258  Jointly calibrate the astrometry and photometry across a set of images.
259 
260  Parameters
261  ----------
262  dataRefs : list of lsst.daf.persistence.ButlerDataRef
263  List of data references to the exposures to be fit.
264  profile_jointcal : bool
265  Profile the individual steps of jointcal.
266 
267  Returns
268  -------
269  pipe.base.Struct
270  struct containing:
271  * dataRefs: the provided data references that were fit (with updated WCSs)
272  * oldWcsList: the original WCS from each dataRef
273  * metrics: dictionary of internally-computed metrics for testing/validation.
274  """
275  if len(dataRefs) == 0:
276  raise ValueError('Need a list of data references!')
277 
278  sourceFluxField = "slot_%sFlux" % (self.sourceSelector.config.sourceFluxType,)
279  jointcalControl = lsst.jointcal.JointcalControl(sourceFluxField)
280  associations = lsst.jointcal.Associations()
281 
282  visit_ccd_to_dataRef = {}
283  oldWcsList = []
284  filters = []
285  load_cat_prof_file = 'jointcal_build_ccdImage.prof' if profile_jointcal else ''
286  with pipeBase.cmdLineTask.profile(load_cat_prof_file):
287  for ref in dataRefs:
288  result = self._build_ccdImage(ref, associations, jointcalControl)
289  oldWcsList.append(result.wcs)
290  visit_ccd_to_dataRef[result.key] = ref
291  filters.append(result.filter)
292  filters = collections.Counter(filters)
293 
294  centers = [ccdImage.getBoresightRaDec() for ccdImage in associations.getCcdImageList()]
295  commonTangentPoint = lsst.afw.coord.averageCoord(centers)
296  self.log.debug("Using common tangent point: %s", commonTangentPoint.getPosition())
297  associations.setCommonTangentPoint(commonTangentPoint.getPosition())
298 
299  # Use external reference catalogs handled by LSST stack mechanism
300  # Get the bounding box overlapping all associated images
301  # ==> This is probably a bad idea to do it this way <== To be improved
302  bbox = associations.getRaDecBBox()
303  center = afwCoord.Coord(bbox.getCenter(), afwGeom.degrees)
304  corner = afwCoord.Coord(bbox.getMax(), afwGeom.degrees)
305  radius = center.angularSeparation(corner).asRadians()
306 
307  # Get astrometry_net_data path
308  anDir = lsst.utils.getPackageDir('astrometry_net_data')
309  if anDir is None:
310  raise RuntimeError("astrometry_net_data is not setup")
311 
312  # Determine a default filter associated with the catalog. See DM-9093
313  defaultFilter = filters.most_common(1)[0][0]
314  self.log.debug("Using %s band for reference flux", defaultFilter)
315 
316  # TODO: need a better way to get the tract.
317  tract = dataRefs[0].dataId['tract']
318 
319  if self.config.doAstrometry:
320  astrometry = self._do_load_refcat_and_fit(associations, defaultFilter, center, radius,
321  name="Astrometry",
322  refObjLoader=self.astrometryRefObjLoader,
323  fit_function=self._fit_astrometry,
324  profile_jointcal=profile_jointcal,
325  tract=tract)
326  else:
327  astrometry = Astrometry(None, None, None)
328 
329  if self.config.doPhotometry:
330  photometry = self._do_load_refcat_and_fit(associations, defaultFilter, center, radius,
331  name="Photometry",
332  refObjLoader=self.photometryRefObjLoader,
333  fit_function=self._fit_photometry,
334  profile_jointcal=profile_jointcal,
335  tract=tract,
336  filters=filters)
337  else:
338  photometry = Photometry(None, None)
339 
340  load_cat_prof_file = 'jointcal_write_results.prof' if profile_jointcal else ''
341  with pipeBase.cmdLineTask.profile(load_cat_prof_file):
342  self._write_results(associations, astrometry.model, photometry.model, visit_ccd_to_dataRef)
343 
344  return pipeBase.Struct(dataRefs=dataRefs, oldWcsList=oldWcsList, metrics=self.metrics)
345 
346  def _do_load_refcat_and_fit(self, associations, defaultFilter, center, radius,
347  name="", refObjLoader=None, filters=[], fit_function=None,
348  tract=None, profile_jointcal=False, match_cut=3.0):
349  """Load reference catalog, perform the fit, and return the result.
350 
351  Parameters
352  ----------
353  associations : lsst.jointcal.Associations
354  The star/reference star associations to fit.
355  defaultFilter : str
356  filter to load from reference catalog.
357  center : lsst.afw.coord.Coord
358  Center of field to load from reference catalog.
359  radius : lsst.afw.geom.Angle
360  On-sky radius to load from reference catalog.
361  name : str
362  Name of thing being fit: "Astrometry" or "Photometry".
363  refObjLoader : lsst.meas.algorithms.LoadReferenceObjectsTask
364  Reference object loader to load from for fit.
365  filters : list of str, optional
366  List of filters to load from the reference catalog.
367  fit_function : function
368  function to call to perform fit (takes associations object).
369  tract : str
370  Name of tract currently being fit.
371  profile_jointcal : bool, optional
372  Separately profile the fitting step.
373  match_cut : float, optional
374  Radius in arcseconds to find cross-catalog matches to during
375  associations.associateCatalogs.
376 
377  Returns
378  -------
379  Result of `fit_function()`
380  """
381  self.log.info("====== Now processing %s...", name)
382  # TODO: this should not print "trying to invert a singular transformation:"
383  # if it does that, something's not right about the WCS...
384  associations.associateCatalogs(match_cut)
385  self.metrics['associated%sFittedStars' % name] = associations.fittedStarListSize()
386 
387  skyCircle = refObjLoader.loadSkyCircle(center,
388  afwGeom.Angle(radius, afwGeom.radians),
389  defaultFilter)
390 
391  # Need memory contiguity to get reference filters as a vector.
392  if not skyCircle.refCat.isContiguous():
393  refCat = skyCircle.refCat.copy(deep=True)
394  else:
395  refCat = skyCircle.refCat
396 
397  # load the reference catalog fluxes.
398  # TODO: Simon will file a ticket for making this better (and making it use the color terms)
399  refFluxes = {}
400  refFluxErrs = {}
401  for filt in filters:
402  filtKeys = lsst.meas.algorithms.getRefFluxKeys(refCat.schema, filt)
403  refFluxes[filt] = refCat.get(filtKeys[0])
404  refFluxErrs[filt] = refCat.get(filtKeys[1])
405 
406  associations.collectRefStars(refCat, self.config.matchCut*afwGeom.arcseconds,
407  skyCircle.fluxField, refFluxes, refFluxErrs)
408  self.metrics['collected%sRefStars' % name] = associations.refStarListSize()
409 
410  associations.selectFittedStars(self.config.minMeasurements)
411  self._check_star_lists(associations, name)
412  self.metrics['selected%sRefStars' % name] = associations.refStarListSize()
413  self.metrics['selected%sFittedStars' % name] = associations.fittedStarListSize()
414  self.metrics['selected%sCcdImageList' % name] = associations.nCcdImagesValidForFit()
415 
416  load_cat_prof_file = 'jointcal_fit_%s.prof'%name if profile_jointcal else ''
417  with pipeBase.cmdLineTask.profile(load_cat_prof_file):
418  result = fit_function(associations)
419  # TODO: this should probably be made optional and turned into a "butler save" somehow.
420  # Save reference and measurement n-tuples for each tract
421  tupleName = "{}_res_{}.list".format(name, tract)
422  result.fit.saveResultTuples(tupleName)
423 
424  return result
425 
426  def _check_star_lists(self, associations, name):
427  # TODO: these should be len(blah), but we need this properly wrapped first.
428  if associations.nCcdImagesValidForFit() == 0:
429  raise RuntimeError('No images in the ccdImageList!')
430  if associations.fittedStarListSize() == 0:
431  raise RuntimeError('No stars in the {} fittedStarList!'.format(name))
432  if associations.refStarListSize() == 0:
433  raise RuntimeError('No stars in the {} reference star list!'.format(name))
434 
435  def _fit_photometry(self, associations):
436  """
437  Fit the photometric data.
438 
439  Parameters
440  ----------
441  associations : lsst.jointcal.Associations
442  The star/reference star associations to fit.
443 
444  Returns
445  -------
446  namedtuple
447  fit : lsst.jointcal.PhotometryFit
448  The photometric fitter used to perform the fit.
449  model : lsst.jointcal.PhotometryModel
450  The photometric model that was fit.
451  """
452  self.log.info("=== Starting photometric fitting...")
453 
454  # TODO: should use pex.config.RegistryField here (see DM-9195)
455  if self.config.photometryModel == "constrained":
456  model = lsst.jointcal.ConstrainedPhotometryModel(associations.getCcdImageList())
457  elif self.config.photometryModel == "simple":
458  model = lsst.jointcal.SimplePhotometryModel(associations.getCcdImageList())
459 
460  fit = lsst.jointcal.PhotometryFit(associations, model)
461  chi2 = fit.computeChi2()
462  self.log.info("Initialized: %s", str(chi2))
463  fit.minimize("Model")
464  chi2 = fit.computeChi2()
465  self.log.info(str(chi2))
466  fit.minimize("Fluxes")
467  chi2 = fit.computeChi2()
468  self.log.info(str(chi2))
469  fit.minimize("Model Fluxes")
470  chi2 = fit.computeChi2()
471  self.log.info("Fit prepared with %s", str(chi2))
472 
473  chi2 = self._iterate_fit(fit, 20, "photometry", "Model Fluxes")
474 
475  self.metrics['photometryFinalChi2'] = chi2.chi2
476  self.metrics['photometryFinalNdof'] = chi2.ndof
477  return Photometry(fit, model)
478 
479  def _fit_astrometry(self, associations):
480  """
481  Fit the astrometric data.
482 
483  Parameters
484  ----------
485  associations : lsst.jointcal.Associations
486  The star/reference star associations to fit.
487 
488  Returns
489  -------
490  namedtuple
491  fit : lsst.jointcal.AstrometryFit
492  The astrometric fitter used to perform the fit.
493  model : lsst.jointcal.AstrometryModel
494  The astrometric model that was fit.
495  sky_to_tan_projection : lsst.jointcal.ProjectionHandler
496  The model for the sky to tangent plane projection that was used in the fit.
497  """
498 
499  self.log.info("=== Starting astrometric fitting...")
500 
501  associations.deprojectFittedStars()
502 
503  # NOTE: need to return sky_to_tan_projection so that it doesn't get garbage collected.
504  # TODO: could we package sky_to_tan_projection and model together so we don't have to manage
505  # them so carefully?
506  sky_to_tan_projection = lsst.jointcal.OneTPPerVisitHandler(associations.getCcdImageList())
507 
508  if self.config.astrometryModel == "constrainedPoly":
509  model = lsst.jointcal.ConstrainedPolyModel(associations.getCcdImageList(),
510  sky_to_tan_projection, True, 0)
511  elif self.config.astrometryModel == "simplePoly":
512  model = lsst.jointcal.SimplePolyModel(associations.getCcdImageList(),
513  sky_to_tan_projection,
514  True, 0, self.config.polyOrder)
515 
516  fit = lsst.jointcal.AstrometryFit(associations, model, self.config.posError)
517  chi2 = fit.computeChi2()
518  self.log.info("Initialized: %s", str(chi2))
519  fit.minimize("Distortions")
520  chi2 = fit.computeChi2()
521  self.log.info(str(chi2))
522  fit.minimize("Positions")
523  chi2 = fit.computeChi2()
524  self.log.info(str(chi2))
525  fit.minimize("Distortions Positions")
526  chi2 = fit.computeChi2()
527  self.log.info(str(chi2))
528 
529  chi2 = self._iterate_fit(fit, 20, "astrometry", "Distortions Positions")
530 
531  self.metrics['astrometryFinalChi2'] = chi2.chi2
532  self.metrics['astrometryFinalNdof'] = chi2.ndof
533 
534  return Astrometry(fit, model, sky_to_tan_projection)
535 
536  def _iterate_fit(self, fit, max_steps, name, whatToFit):
537  """Run fit.minimize up to max_steps times, returning the final chi2."""
538 
539  for i in range(max_steps):
540  r = fit.minimize(whatToFit, 5) # outlier removal at 5 sigma.
541  chi2 = fit.computeChi2()
542  self.log.info(str(chi2))
543  if r == MinimizeResult.Converged:
544  self.log.debug("fit has converged - no more outliers - redo minimixation"
545  "one more time in case we have lost accuracy in rank update")
546  # Redo minimization one more time in case we have lost accuracy in rank update
547  r = fit.minimize(whatToFit, 5) # outliers removal at 5 sigma.
548  chi2 = fit.computeChi2()
549  self.log.info("Fit completed with: %s", str(chi2))
550  break
551  elif r == MinimizeResult.Failed:
552  self.log.warn("minimization failed")
553  break
554  elif r == MinimizeResult.Chi2Increased:
555  self.log.warn("still some ouliers but chi2 increases - retry")
556  else:
557  self.log.error("unxepected return code from minimize")
558  break
559  else:
560  self.log.error("%s failed to converge after %d steps"%(name, max_steps))
561 
562  return chi2
563 
564  def _write_results(self, associations, astrom_model, photom_model, visit_ccd_to_dataRef):
565  """
566  Write the fitted results (photometric and astrometric) to a new 'wcs' dataRef.
567 
568  Parameters
569  ----------
570  associations : lsst.jointcal.Associations
571  The star/reference star associations to fit.
572  astrom_model : lsst.jointcal.AstrometryModel
573  The astrometric model that was fit.
574  photom_model : lsst.jointcal.PhotometryModel
575  The photometric model that was fit.
576  visit_ccd_to_dataRef : dict of Key: lsst.daf.persistence.ButlerDataRef
577  dict of ccdImage identifiers to dataRefs that were fit
578  """
579 
580  ccdImageList = associations.getCcdImageList()
581  for ccdImage in ccdImageList:
582  # TODO: there must be a better way to identify this ccdImage than a visit,ccd pair?
583  ccd = ccdImage.ccdId
584  visit = ccdImage.visit
585  dataRef = visit_ccd_to_dataRef[(visit, ccd)]
586  exp = afwImage.ExposureI(0, 0)
587  if self.config.doAstrometry:
588  self.log.info("Updating WCS for visit: %d, ccd: %d", visit, ccd)
589  tanSip = astrom_model.produceSipWcs(ccdImage)
590  tanWcs = lsst.jointcal.gtransfoToTanWcs(tanSip, ccdImage.imageFrame, False)
591  exp.setWcs(tanWcs)
592  if self.config.doPhotometry:
593  self.log.info("Updating Calib for visit: %d, ccd: %d", visit, ccd)
594  # start with the original calib saved to the ccdImage
595  fluxMag0 = ccdImage.getPhotoCalib().getInstFluxMag0()
596  fluxMag0Err = ccdImage.getPhotoCalib().getInstFluxMag0Err()
597  exp.getCalib().setFluxMag0(fluxMag0/photom_model.photomFactor(ccdImage), fluxMag0Err)
598  try:
599  dataRef.put(exp, 'wcs')
600  except pexExceptions.Exception as e:
601  self.log.fatal('Failed to write updated Wcs and Calib: %s', str(e))
602  raise e
this is the model used to fit independent CCDs, meaning that there is no instrument model...
def _build_ccdImage(self, dataRef, associations, jointcalControl)
Definition: jointcal.py:203
def _fit_photometry(self, associations)
Definition: jointcal.py:435
def _iterate_fit(self, fit, max_steps, name, whatToFit)
Definition: jointcal.py:536
def getTargetList(parsedCmd, kwargs)
Definition: jointcal.py:46
def _check_star_lists(self, associations, name)
Definition: jointcal.py:426
The class that implements the relations between MeasuredStar and FittedStar.
Definition: Associations.h:28
A projection handler in which all CCDs from the same visit have the same tangent point.
This is the model used to fit mappings as the combination of a transformation depending on the chip n...
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)
Definition: jointcal.py:348
Class that handles the photometric least squares problem.
Definition: PhotometryFit.h:20
def _fit_astrometry(self, associations)
Definition: jointcal.py:479
boost::shared_ptr< lsst::afw::image::TanWcs > gtransfoToTanWcs(const lsst::jointcal::TanSipPix2RaDec wcsTransfo, const lsst::jointcal::Frame &ccdFrame, const bool noLowOrderSipTerms=false)
Transform the other way around.
Class that handles the astrometric least squares problem.
Definition: AstrometryFit.h:55
def _write_results(self, associations, astrom_model, photom_model, visit_ccd_to_dataRef)
Definition: jointcal.py:564
def run(self, dataRefs, profile_jointcal=False)
Definition: jointcal.py:256
Photometric response model which has a single photometric factor per CcdImage.
def __init__(self, butler=None, profile_jointcal=False, kwargs)
Definition: jointcal.py:163