lsst.fgcmcal  20.0.0-5-gfcebe35+a596b7bc26
fgcmFitCycle.py
Go to the documentation of this file.
1 # See COPYRIGHT file at the top of the source tree.
2 #
3 # This file is part of fgcmcal.
4 #
5 # Developed for the LSST Data Management System.
6 # This product includes software developed by the LSST Project
7 # (https://www.lsst.org).
8 # See the COPYRIGHT file at the top-level directory of this distribution
9 # for details of code ownership.
10 #
11 # This program is free software: you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation, either version 3 of the License, or
14 # (at your option) any later version.
15 #
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
20 #
21 # You should have received a copy of the GNU General Public License
22 # along with this program. If not, see <https://www.gnu.org/licenses/>.
23 """Perform a single fit cycle of FGCM.
24 
25 This task runs a single "fit cycle" of fgcm. Prior to running this task
26 one must run both fgcmMakeLut (to construct the atmosphere and instrumental
27 look-up-table) and fgcmBuildStars (to extract visits and star observations
28 for the global fit).
29 
30 The fgcmFitCycle is meant to be run multiple times, and is tracked by the
31 'cycleNumber'. After each run of the fit cycle, diagnostic plots should
32 be inspected to set parameters for outlier rejection on the following
33 cycle. Please see the fgcmcal Cookbook for details.
34 """
35 
36 import sys
37 import traceback
38 import copy
39 
40 import numpy as np
41 
42 import lsst.pex.config as pexConfig
43 import lsst.pipe.base as pipeBase
44 import lsst.afw.table as afwTable
45 
46 from .utilities import makeConfigDict, translateFgcmLut, translateVisitCatalog
47 from .utilities import extractReferenceMags
48 from .utilities import computeCcdOffsets, makeZptSchema, makeZptCat
49 from .utilities import makeAtmSchema, makeAtmCat, makeStdSchema, makeStdCat
50 from .sedterms import SedboundarytermDict, SedtermDict
51 
52 import fgcm
53 
54 __all__ = ['FgcmFitCycleConfig', 'FgcmFitCycleTask', 'FgcmFitCycleRunner']
55 
56 
57 class FgcmFitCycleConfig(pexConfig.Config):
58  """Config for FgcmFitCycle"""
59 
60  bands = pexConfig.ListField(
61  doc="Bands to run calibration",
62  dtype=str,
63  default=[],
64  )
65  fitFlag = pexConfig.ListField(
66  doc=("Flag for which bands are directly constrained in the FGCM fit. "
67  "Bands set to 0 will have the atmosphere constrained from observations "
68  "in other bands on the same night. Must be same length as config.bands, "
69  "and matched band-by-band."),
70  dtype=int,
71  default=(0,),
72  optional=True,
73  deprecated=("This field is no longer used, and has been deprecated by DM-23699. "
74  "It will be removed after v20. Use fitBands instead."),
75  )
76  fitBands = pexConfig.ListField(
77  doc=("Bands to use in atmospheric fit. The bands not listed here will have "
78  "the atmosphere constrained from the 'fitBands' on the same night. "
79  "Must be a subset of `config.bands`"),
80  dtype=str,
81  default=[],
82  )
83  requiredFlag = pexConfig.ListField(
84  doc=("Flag for which bands are required for a star to be considered a calibration "
85  "star in the FGCM fit. Typically this should be the same as fitFlag. Must "
86  "be same length as config.bands, and matched band-by-band."),
87  dtype=int,
88  default=(0,),
89  optional=True,
90  deprecated=("This field is no longer used, and has been deprecated by DM-23699. "
91  "It will be removed after v20. Use requiredBands instead."),
92  )
93  requiredBands = pexConfig.ListField(
94  doc=("Bands that are required for a star to be considered a calibration star. "
95  "Must be a subset of `config.bands`"),
96  dtype=str,
97  default=[],
98  )
99  filterMap = pexConfig.DictField(
100  doc="Mapping from 'filterName' to band.",
101  keytype=str,
102  itemtype=str,
103  default={},
104  )
105  doReferenceCalibration = pexConfig.Field(
106  doc="Use reference catalog as additional constraint on calibration",
107  dtype=bool,
108  default=True,
109  )
110  refStarSnMin = pexConfig.Field(
111  doc="Reference star signal-to-noise minimum to use in calibration. Set to <=0 for no cut.",
112  dtype=float,
113  default=50.0,
114  )
115  refStarOutlierNSig = pexConfig.Field(
116  doc=("Number of sigma compared to average mag for reference star to be considered an outlier. "
117  "Computed per-band, and if it is an outlier in any band it is rejected from fits."),
118  dtype=float,
119  default=4.0,
120  )
121  applyRefStarColorCuts = pexConfig.Field(
122  doc="Apply color cuts to reference stars?",
123  dtype=bool,
124  default=True,
125  )
126  nCore = pexConfig.Field(
127  doc="Number of cores to use",
128  dtype=int,
129  default=4,
130  )
131  nStarPerRun = pexConfig.Field(
132  doc="Number of stars to run in each chunk",
133  dtype=int,
134  default=200000,
135  )
136  nExpPerRun = pexConfig.Field(
137  doc="Number of exposures to run in each chunk",
138  dtype=int,
139  default=1000,
140  )
141  reserveFraction = pexConfig.Field(
142  doc="Fraction of stars to reserve for testing",
143  dtype=float,
144  default=0.1,
145  )
146  freezeStdAtmosphere = pexConfig.Field(
147  doc="Freeze atmosphere parameters to standard (for testing)",
148  dtype=bool,
149  default=False,
150  )
151  precomputeSuperStarInitialCycle = pexConfig.Field(
152  doc="Precompute superstar flat for initial cycle",
153  dtype=bool,
154  default=False,
155  )
156  superStarSubCcd = pexConfig.Field(
157  doc="Compute superstar flat on sub-ccd scale",
158  dtype=bool,
159  default=True,
160  optional=True,
161  deprecated=("This field is no longer used, and has been deprecated by DM-23699. "
162  "It will be removed after v20. Use superStarSubCcdDict instead."),
163  )
164  superStarSubCcdDict = pexConfig.DictField(
165  doc=("Per-band specification on whether to compute superstar flat on sub-ccd scale. "
166  "Must have one entry per band."),
167  keytype=str,
168  itemtype=bool,
169  default={},
170  )
171  superStarSubCcdChebyshevOrder = pexConfig.Field(
172  doc=("Order of the 2D chebyshev polynomials for sub-ccd superstar fit. "
173  "Global default is first-order polynomials, and should be overridden "
174  "on a camera-by-camera basis depending on the ISR."),
175  dtype=int,
176  default=1,
177  )
178  superStarSubCcdTriangular = pexConfig.Field(
179  doc=("Should the sub-ccd superstar chebyshev matrix be triangular to "
180  "suppress high-order cross terms?"),
181  dtype=bool,
182  default=False,
183  )
184  superStarSigmaClip = pexConfig.Field(
185  doc="Number of sigma to clip outliers when selecting for superstar flats",
186  dtype=float,
187  default=5.0,
188  )
189  ccdGraySubCcd = pexConfig.Field(
190  doc="Compute CCD gray terms on sub-ccd scale",
191  dtype=bool,
192  default=False,
193  optional=True,
194  deprecated=("This field is no longer used, and has been deprecated by DM-23699. "
195  "It will be removed after v20. Use ccdGraySubCcdDict instead."),
196  )
197  ccdGraySubCcdDict = pexConfig.DictField(
198  doc=("Per-band specification on whether to compute achromatic per-ccd residual "
199  "('ccd gray') on a sub-ccd scale."),
200  keytype=str,
201  itemtype=bool,
202  default={},
203  )
204  ccdGraySubCcdChebyshevOrder = pexConfig.Field(
205  doc="Order of the 2D chebyshev polynomials for sub-ccd gray fit.",
206  dtype=int,
207  default=1,
208  )
209  ccdGraySubCcdTriangular = pexConfig.Field(
210  doc=("Should the sub-ccd gray chebyshev matrix be triangular to "
211  "suppress high-order cross terms?"),
212  dtype=bool,
213  default=True,
214  )
215  cycleNumber = pexConfig.Field(
216  doc=("FGCM fit cycle number. This is automatically incremented after each run "
217  "and stage of outlier rejection. See cookbook for details."),
218  dtype=int,
219  default=None,
220  )
221  isFinalCycle = pexConfig.Field(
222  doc=("Is this the final cycle of the fitting? Will automatically compute final "
223  "selection of stars and photometric exposures, and will output zeropoints "
224  "and standard stars for use in fgcmOutputProducts"),
225  dtype=bool,
226  default=False,
227  )
228  maxIterBeforeFinalCycle = pexConfig.Field(
229  doc=("Maximum fit iterations, prior to final cycle. The number of iterations "
230  "will always be 0 in the final cycle for cleanup and final selection."),
231  dtype=int,
232  default=50,
233  )
234  deltaMagBkgOffsetPercentile = pexConfig.Field(
235  doc=("Percentile brightest stars on a visit/ccd to use to compute net "
236  "offset from local background subtraction."),
237  dtype=float,
238  default=0.25,
239  )
240  deltaMagBkgPerCcd = pexConfig.Field(
241  doc=("Compute net offset from local background subtraction per-ccd? "
242  "Otherwise, use computation per visit."),
243  dtype=bool,
244  default=False,
245  )
246  utBoundary = pexConfig.Field(
247  doc="Boundary (in UTC) from day-to-day",
248  dtype=float,
249  default=None,
250  )
251  washMjds = pexConfig.ListField(
252  doc="Mirror wash MJDs",
253  dtype=float,
254  default=(0.0,),
255  )
256  epochMjds = pexConfig.ListField(
257  doc="Epoch boundaries in MJD",
258  dtype=float,
259  default=(0.0,),
260  )
261  minObsPerBand = pexConfig.Field(
262  doc="Minimum good observations per band",
263  dtype=int,
264  default=2,
265  )
266  # TODO: When DM-16511 is done, it will be possible to get the
267  # telescope latitude directly from the camera.
268  latitude = pexConfig.Field(
269  doc="Observatory latitude",
270  dtype=float,
271  default=None,
272  )
273  brightObsGrayMax = pexConfig.Field(
274  doc="Maximum gray extinction to be considered bright observation",
275  dtype=float,
276  default=0.15,
277  )
278  minStarPerCcd = pexConfig.Field(
279  doc=("Minimum number of good stars per CCD to be used in calibration fit. "
280  "CCDs with fewer stars will have their calibration estimated from other "
281  "CCDs in the same visit, with zeropoint error increased accordingly."),
282  dtype=int,
283  default=5,
284  )
285  minCcdPerExp = pexConfig.Field(
286  doc=("Minimum number of good CCDs per exposure/visit to be used in calibration fit. "
287  "Visits with fewer good CCDs will have CCD zeropoints estimated where possible."),
288  dtype=int,
289  default=5,
290  )
291  maxCcdGrayErr = pexConfig.Field(
292  doc="Maximum error on CCD gray offset to be considered photometric",
293  dtype=float,
294  default=0.05,
295  )
296  minStarPerExp = pexConfig.Field(
297  doc=("Minimum number of good stars per exposure/visit to be used in calibration fit. "
298  "Visits with fewer good stars will have CCD zeropoints estimated where possible."),
299  dtype=int,
300  default=600,
301  )
302  minExpPerNight = pexConfig.Field(
303  doc="Minimum number of good exposures/visits to consider a partly photometric night",
304  dtype=int,
305  default=10,
306  )
307  expGrayInitialCut = pexConfig.Field(
308  doc=("Maximum exposure/visit gray value for initial selection of possible photometric "
309  "observations."),
310  dtype=float,
311  default=-0.25,
312  )
313  expGrayPhotometricCut = pexConfig.ListField(
314  doc=("Maximum (negative) exposure gray for a visit to be considered photometric. "
315  "Must be same length as config.bands, and matched band-by-band."),
316  dtype=float,
317  default=(0.0,),
318  optional=True,
319  deprecated=("This field is no longer used, and has been deprecated by DM-23699. "
320  "It will be removed after v20. Use expGrayPhotometricCutDict instead."),
321  )
322  expGrayPhotometricCutDict = pexConfig.DictField(
323  doc=("Per-band specification on maximum (negative) achromatic exposure residual "
324  "('gray term') for a visit to be considered photometric. Must have one "
325  "entry per band. Broad-band filters should be -0.05."),
326  keytype=str,
327  itemtype=float,
328  default={},
329  )
330  expGrayHighCut = pexConfig.ListField(
331  doc=("Maximum (positive) exposure gray for a visit to be considered photometric. "
332  "Must be same length as config.bands, and matched band-by-band."),
333  dtype=float,
334  default=(0.0,),
335  optional=True,
336  deprecated=("This field is no longer used, and has been deprecated by DM-23699. "
337  "It will be removed after v20. Use expGrayHighCutDict instead."),
338  )
339  expGrayHighCutDict = pexConfig.DictField(
340  doc=("Per-band specification on maximum (positive) achromatic exposure residual "
341  "('gray term') for a visit to be considered photometric. Must have one "
342  "entry per band. Broad-band filters should be 0.2."),
343  keytype=str,
344  itemtype=float,
345  default={},
346  )
347  expGrayRecoverCut = pexConfig.Field(
348  doc=("Maximum (negative) exposure gray to be able to recover bad ccds via interpolation. "
349  "Visits with more gray extinction will only get CCD zeropoints if there are "
350  "sufficient star observations (minStarPerCcd) on that CCD."),
351  dtype=float,
352  default=-1.0,
353  )
354  expVarGrayPhotometricCut = pexConfig.Field(
355  doc="Maximum exposure variance to be considered possibly photometric",
356  dtype=float,
357  default=0.0005,
358  optional=True,
359  deprecated=("This field is no longer used, and has been deprecated by DM-23699. "
360  "It will be removed after v20. Use expVarGrayPhotometricCutDict instead."),
361  )
362  expVarGrayPhotometricCutDict = pexConfig.DictField(
363  doc=("Per-band specification on maximum exposure variance to be considered possibly "
364  "photometric. Must have one entry per band. Broad-band filters should be "
365  "0.0005."),
366  keytype=str,
367  itemtype=float,
368  default={},
369  )
370  expGrayErrRecoverCut = pexConfig.Field(
371  doc=("Maximum exposure gray error to be able to recover bad ccds via interpolation. "
372  "Visits with more gray variance will only get CCD zeropoints if there are "
373  "sufficient star observations (minStarPerCcd) on that CCD."),
374  dtype=float,
375  default=0.05,
376  )
377  aperCorrFitNBins = pexConfig.Field(
378  doc=("Number of aperture bins used in aperture correction fit. When set to 0"
379  "no fit will be performed, and the config.aperCorrInputSlopes will be "
380  "used if available."),
381  dtype=int,
382  default=10,
383  )
384  aperCorrInputSlopes = pexConfig.ListField(
385  doc=("Aperture correction input slope parameters. These are used on the first "
386  "fit iteration, and aperture correction parameters will be updated from "
387  "the data if config.aperCorrFitNBins > 0. It is recommended to set this"
388  "when there is insufficient data to fit the parameters (e.g. tract mode). "
389  "If set, must be same length as config.bands, and matched band-by-band."),
390  dtype=float,
391  default=[],
392  optional=True,
393  deprecated=("This field is no longer used, and has been deprecated by DM-23699. "
394  "It will be removed after v20. Use aperCorrInputSlopeDict instead."),
395  )
396  aperCorrInputSlopeDict = pexConfig.DictField(
397  doc=("Per-band specification of aperture correction input slope parameters. These "
398  "are used on the first fit iteration, and aperture correction parameters will "
399  "be updated from the data if config.aperCorrFitNBins > 0. It is recommended "
400  "to set this when there is insufficient data to fit the parameters (e.g. "
401  "tract mode)."),
402  keytype=str,
403  itemtype=float,
404  default={},
405  )
406  sedFudgeFactors = pexConfig.ListField(
407  doc=("Fudge factors for computing linear SED from colors. Must be same length as "
408  "config.bands, and matched band-by-band."),
409  dtype=float,
410  default=(0,),
411  optional=True,
412  deprecated=("This field has been deprecated and will be removed after v20. "
413  "Please use sedSlopeTermMap and sedSlopeMap."),
414  )
415  sedboundaryterms = pexConfig.ConfigField(
416  doc="Mapping from bands to SED boundary term names used is sedterms.",
417  dtype=SedboundarytermDict,
418  )
419  sedterms = pexConfig.ConfigField(
420  doc="Mapping from terms to bands for fgcm linear SED approximations.",
421  dtype=SedtermDict,
422  )
423  sigFgcmMaxErr = pexConfig.Field(
424  doc="Maximum mag error for fitting sigma_FGCM",
425  dtype=float,
426  default=0.01,
427  )
428  sigFgcmMaxEGray = pexConfig.ListField(
429  doc=("Maximum (absolute) gray value for observation in sigma_FGCM. "
430  "May be 1 element (same for all bands) or the same length as config.bands."),
431  dtype=float,
432  default=(0.05,),
433  optional=True,
434  deprecated=("This field is no longer used, and has been deprecated by DM-23699. "
435  "It will be removed after v20. Use sigFgcmMaxEGrayDict instead."),
436  )
437  sigFgcmMaxEGrayDict = pexConfig.DictField(
438  doc=("Per-band specification for maximum (absolute) achromatic residual (gray value) "
439  "for observations in sigma_fgcm (raw repeatability). Broad-band filters "
440  "should be 0.05."),
441  keytype=str,
442  itemtype=float,
443  default={},
444  )
445  ccdGrayMaxStarErr = pexConfig.Field(
446  doc=("Maximum error on a star observation to use in ccd gray (achromatic residual) "
447  "computation"),
448  dtype=float,
449  default=0.10,
450  )
451  approxThroughput = pexConfig.ListField(
452  doc=("Approximate overall throughput at start of calibration observations. "
453  "May be 1 element (same for all bands) or the same length as config.bands."),
454  dtype=float,
455  default=(1.0, ),
456  optional=True,
457  deprecated=("This field is no longer used, and has been deprecated by DM-23699. "
458  "It will be removed after v20. Use approxThroughputDict instead."),
459  )
460  approxThroughputDict = pexConfig.DictField(
461  doc=("Per-band specification of the approximate overall throughput at the start of "
462  "calibration observations. Must have one entry per band. Typically should "
463  "be 1.0."),
464  keytype=str,
465  itemtype=float,
466  default={},
467  )
468  sigmaCalRange = pexConfig.ListField(
469  doc="Allowed range for systematic error floor estimation",
470  dtype=float,
471  default=(0.001, 0.003),
472  )
473  sigmaCalFitPercentile = pexConfig.ListField(
474  doc="Magnitude percentile range to fit systematic error floor",
475  dtype=float,
476  default=(0.05, 0.15),
477  )
478  sigmaCalPlotPercentile = pexConfig.ListField(
479  doc="Magnitude percentile range to plot systematic error floor",
480  dtype=float,
481  default=(0.05, 0.95),
482  )
483  sigma0Phot = pexConfig.Field(
484  doc="Systematic error floor for all zeropoints",
485  dtype=float,
486  default=0.003,
487  )
488  mapLongitudeRef = pexConfig.Field(
489  doc="Reference longitude for plotting maps",
490  dtype=float,
491  default=0.0,
492  )
493  mapNSide = pexConfig.Field(
494  doc="Healpix nside for plotting maps",
495  dtype=int,
496  default=256,
497  )
498  outfileBase = pexConfig.Field(
499  doc="Filename start for plot output files",
500  dtype=str,
501  default=None,
502  )
503  starColorCuts = pexConfig.ListField(
504  doc="Encoded star-color cuts (to be cleaned up)",
505  dtype=str,
506  default=("NO_DATA",),
507  )
508  colorSplitIndices = pexConfig.ListField(
509  doc="Band indices to use to split stars by color",
510  dtype=int,
511  default=None,
512  optional=True,
513  deprecated=("This field is no longer used, and has been deprecated by DM-23699. "
514  "It will be removed after v20. Use colorSplitBands instead."),
515  )
516  colorSplitBands = pexConfig.ListField(
517  doc="Band names to use to split stars by color. Must have 2 entries.",
518  dtype=str,
519  length=2,
520  default=('g', 'i'),
521  )
522  modelMagErrors = pexConfig.Field(
523  doc="Should FGCM model the magnitude errors from sky/fwhm? (False means trust inputs)",
524  dtype=bool,
525  default=True,
526  )
527  useQuadraticPwv = pexConfig.Field(
528  doc="Model PWV with a quadratic term for variation through the night?",
529  dtype=bool,
530  default=False,
531  )
532  instrumentParsPerBand = pexConfig.Field(
533  doc=("Model instrumental parameters per band? "
534  "Otherwise, instrumental parameters (QE changes with time) are "
535  "shared among all bands."),
536  dtype=bool,
537  default=False,
538  )
539  instrumentSlopeMinDeltaT = pexConfig.Field(
540  doc=("Minimum time change (in days) between observations to use in constraining "
541  "instrument slope."),
542  dtype=float,
543  default=20.0,
544  )
545  fitMirrorChromaticity = pexConfig.Field(
546  doc="Fit (intraband) mirror chromatic term?",
547  dtype=bool,
548  default=False,
549  )
550  coatingMjds = pexConfig.ListField(
551  doc="Mirror coating dates in MJD",
552  dtype=float,
553  default=(0.0,),
554  )
555  outputStandardsBeforeFinalCycle = pexConfig.Field(
556  doc="Output standard stars prior to final cycle? Used in debugging.",
557  dtype=bool,
558  default=False,
559  )
560  outputZeropointsBeforeFinalCycle = pexConfig.Field(
561  doc="Output standard stars prior to final cycle? Used in debugging.",
562  dtype=bool,
563  default=False,
564  )
565  useRepeatabilityForExpGrayCuts = pexConfig.ListField(
566  doc=("Use star repeatability (instead of exposures) for computing photometric "
567  "cuts? Recommended for tract mode or bands with few exposures. "
568  "May be 1 element (same for all bands) or the same length as config.bands."),
569  dtype=bool,
570  default=(False,),
571  optional=True,
572  deprecated=("This field is no longer used, and has been deprecated by DM-23699. "
573  "It will be removed after v20. Use useRepeatabilityForExpGrayCutsDict instead."),
574  )
575  useRepeatabilityForExpGrayCutsDict = pexConfig.DictField(
576  doc=("Per-band specification on whether to use star repeatability (instead of exposures) "
577  "for computing photometric cuts. Recommended for tract mode or bands with few visits."),
578  keytype=str,
579  itemtype=bool,
580  default={},
581  )
582  autoPhotometricCutNSig = pexConfig.Field(
583  doc=("Number of sigma for automatic computation of (low) photometric cut. "
584  "Cut is based on exposure gray width (per band), unless "
585  "useRepeatabilityForExpGrayCuts is set, in which case the star "
586  "repeatability is used (also per band)."),
587  dtype=float,
588  default=3.0,
589  )
590  autoHighCutNSig = pexConfig.Field(
591  doc=("Number of sigma for automatic computation of (high) outlier cut. "
592  "Cut is based on exposure gray width (per band), unless "
593  "useRepeatabilityForExpGrayCuts is set, in which case the star "
594  "repeatability is used (also per band)."),
595  dtype=float,
596  default=4.0,
597  )
598  quietMode = pexConfig.Field(
599  doc="Be less verbose with logging.",
600  dtype=bool,
601  default=False,
602  )
603 
604  def setDefaults(self):
605  pass
606 
607  def validate(self):
608  super().validate()
609 
610  for band in self.fitBands:
611  if band not in self.bands:
612  msg = 'fitBand %s not in bands' % (band)
613  raise pexConfig.FieldValidationError(FgcmFitCycleConfig.fitBands, self, msg)
614  for band in self.requiredBands:
615  if band not in self.bands:
616  msg = 'requiredBand %s not in bands' % (band)
617  raise pexConfig.FieldValidationError(FgcmFitCycleConfig.requiredBands, self, msg)
618  for band in self.colorSplitBands:
619  if band not in self.bands:
620  msg = 'colorSplitBand %s not in bands' % (band)
621  raise pexConfig.FieldValidationError(FgcmFitCycleConfig.colorSplitBands, self, msg)
622  for band in self.bands:
623  if band not in self.superStarSubCcdDict:
624  msg = 'band %s not in superStarSubCcdDict' % (band)
625  raise pexConfig.FieldValidationError(FgcmFitCycleConfig.superStarSubCcdDict,
626  self, msg)
627  if band not in self.ccdGraySubCcdDict:
628  msg = 'band %s not in ccdGraySubCcdDict' % (band)
629  raise pexConfig.FieldValidationError(FgcmFitCycleConfig.ccdGraySubCcdDict,
630  self, msg)
631  if band not in self.expGrayPhotometricCutDict:
632  msg = 'band %s not in expGrayPhotometricCutDict' % (band)
633  raise pexConfig.FieldValidationError(FgcmFitCycleConfig.expGrayPhotometricCutDict,
634  self, msg)
635  if band not in self.expGrayHighCutDict:
636  msg = 'band %s not in expGrayHighCutDict' % (band)
637  raise pexConfig.FieldValidationError(FgcmFitCycleConfig.expGrayHighCutDict,
638  self, msg)
639  if band not in self.expVarGrayPhotometricCutDict:
640  msg = 'band %s not in expVarGrayPhotometricCutDict' % (band)
641  raise pexConfig.FieldValidationError(FgcmFitCycleConfig.expVarGrayPhotometricCutDict,
642  self, msg)
643  if band not in self.sigFgcmMaxEGrayDict:
644  msg = 'band %s not in sigFgcmMaxEGrayDict' % (band)
645  raise pexConfig.FieldValidationError(FgcmFitCycleConfig.sigFgcmMaxEGrayDict,
646  self, msg)
647  if band not in self.approxThroughputDict:
648  msg = 'band %s not in approxThroughputDict' % (band)
649  raise pexConfig.FieldValidationError(FgcmFitCycleConfig.approxThroughputDict,
650  self, msg)
651  if band not in self.useRepeatabilityForExpGrayCutsDict:
652  msg = 'band %s not in useRepeatabilityForExpGrayCutsDict' % (band)
653  raise pexConfig.FieldValidationError(FgcmFitCycleConfig.useRepeatabilityForExpGrayCutsDict,
654  self, msg)
655 
656 
657 class FgcmFitCycleRunner(pipeBase.ButlerInitializedTaskRunner):
658  """Subclass of TaskRunner for fgcmFitCycleTask
659 
660  fgcmFitCycleTask.run() takes one argument, the butler, and uses
661  stars and visits previously extracted from dataRefs by
662  fgcmBuildStars.
663  This Runner does not perform any dataRef parallelization, but the FGCM
664  code called by the Task uses python multiprocessing (see the "ncores"
665  config option).
666  """
667 
668  @staticmethod
669  def getTargetList(parsedCmd):
670  """
671  Return a list with one element, the butler.
672  """
673  return [parsedCmd.butler]
674 
675  def __call__(self, butler):
676  """
677  Parameters
678  ----------
679  butler: `lsst.daf.persistence.Butler`
680 
681  Returns
682  -------
683  exitStatus: `list` with `pipeBase.Struct`
684  exitStatus (0: success; 1: failure)
685  """
686 
687  task = self.TaskClass(config=self.config, log=self.log)
688 
689  exitStatus = 0
690  if self.doRaise:
691  task.runDataRef(butler)
692  else:
693  try:
694  task.runDataRef(butler)
695  except Exception as e:
696  exitStatus = 1
697  task.log.fatal("Failed: %s" % e)
698  if not isinstance(e, pipeBase.TaskError):
699  traceback.print_exc(file=sys.stderr)
700 
701  task.writeMetadata(butler)
702 
703  # The task does not return any results:
704  return [pipeBase.Struct(exitStatus=exitStatus)]
705 
706  def run(self, parsedCmd):
707  """
708  Run the task, with no multiprocessing
709 
710  Parameters
711  ----------
712  parsedCmd: ArgumentParser parsed command line
713  """
714 
715  resultList = []
716 
717  if self.precall(parsedCmd):
718  targetList = self.getTargetList(parsedCmd)
719  # make sure that we only get 1
720  resultList = self(targetList[0])
721 
722  return resultList
723 
724 
725 class FgcmFitCycleTask(pipeBase.CmdLineTask):
726  """
727  Run Single fit cycle for FGCM global calibration
728  """
729 
730  ConfigClass = FgcmFitCycleConfig
731  RunnerClass = FgcmFitCycleRunner
732  _DefaultName = "fgcmFitCycle"
733 
734  def __init__(self, butler=None, **kwargs):
735  """
736  Instantiate an fgcmFitCycle.
737 
738  Parameters
739  ----------
740  butler : `lsst.daf.persistence.Butler`
741  """
742 
743  pipeBase.CmdLineTask.__init__(self, **kwargs)
744 
745  # no saving of metadata for now
746  def _getMetadataName(self):
747  return None
748 
749  @pipeBase.timeMethod
750  def runDataRef(self, butler):
751  """
752  Run a single fit cycle for FGCM
753 
754  Parameters
755  ----------
756  butler: `lsst.daf.persistence.Butler`
757  """
758 
759  self._fgcmFitCycle(butler)
760 
761  def writeConfig(self, butler, clobber=False, doBackup=True):
762  """Write the configuration used for processing the data, or check that an existing
763  one is equal to the new one if present. This is an override of the regular
764  version from pipe_base that knows about fgcmcycle.
765 
766  Parameters
767  ----------
768  butler : `lsst.daf.persistence.Butler`
769  Data butler used to write the config. The config is written to dataset type
770  `CmdLineTask._getConfigName`.
771  clobber : `bool`, optional
772  A boolean flag that controls what happens if a config already has been saved:
773  - `True`: overwrite or rename the existing config, depending on ``doBackup``.
774  - `False`: raise `TaskError` if this config does not match the existing config.
775  doBackup : `bool`, optional
776  Set to `True` to backup the config files if clobbering.
777  """
778  configName = self._getConfigName()
779  if configName is None:
780  return
781  if clobber:
782  butler.put(self.config, configName, doBackup=doBackup, fgcmcycle=self.config.cycleNumber)
783  elif butler.datasetExists(configName, write=True, fgcmcycle=self.config.cycleNumber):
784  # this may be subject to a race condition; see #2789
785  try:
786  oldConfig = butler.get(configName, immediate=True, fgcmcycle=self.config.cycleNumber)
787  except Exception as exc:
788  raise type(exc)("Unable to read stored config file %s (%s); consider using --clobber-config" %
789  (configName, exc))
790 
791  def logConfigMismatch(msg):
792  self.log.fatal("Comparing configuration: %s", msg)
793 
794  if not self.config.compare(oldConfig, shortcut=False, output=logConfigMismatch):
795  raise pipeBase.TaskError(
796  ("Config does not match existing task config %r on disk; tasks configurations " +
797  "must be consistent within the same output repo (override with --clobber-config)") %
798  (configName,))
799  else:
800  butler.put(self.config, configName, fgcmcycle=self.config.cycleNumber)
801 
802  def _fgcmFitCycle(self, butler):
803  """
804  Run the fit cycle
805 
806  Parameters
807  ----------
808  butler: `lsst.daf.persistence.Butler`
809  """
810 
811  self._checkDatasetsExist(butler)
812 
813  # Set defaults on whether to output standards and zeropoints
814  self.maxIter = self.config.maxIterBeforeFinalCycle
815  self.outputStandards = self.config.outputStandardsBeforeFinalCycle
816  self.outputZeropoints = self.config.outputZeropointsBeforeFinalCycle
817  self.resetFitParameters = True
818 
819  if self.config.isFinalCycle:
820  # This is the final fit cycle, so we do not want to reset fit
821  # parameters, we want to run a final "clean-up" with 0 fit iterations,
822  # and we always want to output standards and zeropoints
823  self.maxIter = 0
824  self.outputStandards = True
825  self.outputZeropoints = True
826  self.resetFitParameters = False
827 
828  camera = butler.get('camera')
829  configDict = makeConfigDict(self.config, self.log, camera,
830  self.maxIter, self.resetFitParameters,
831  self.outputZeropoints)
832 
833  lutCat = butler.get('fgcmLookUpTable')
834  fgcmLut, lutIndexVals, lutStd = translateFgcmLut(lutCat, dict(self.config.filterMap))
835  del lutCat
836 
837  # next we need the exposure/visit information
838 
839  # fgcmExpInfo = self._loadVisitCatalog(butler)
840  visitCat = butler.get('fgcmVisitCatalog')
841  fgcmExpInfo = translateVisitCatalog(visitCat)
842  del visitCat
843 
844  # Use the first orientation.
845  # TODO: DM-21215 will generalize to arbitrary camera orientations
846  ccdOffsets = computeCcdOffsets(camera, fgcmExpInfo['TELROT'][0])
847 
848  noFitsDict = {'lutIndex': lutIndexVals,
849  'lutStd': lutStd,
850  'expInfo': fgcmExpInfo,
851  'ccdOffsets': ccdOffsets}
852 
853  # set up the fitter object
854  fgcmFitCycle = fgcm.FgcmFitCycle(configDict, useFits=False,
855  noFitsDict=noFitsDict, noOutput=True)
856 
857  # create the parameter object
858  if (fgcmFitCycle.initialCycle):
859  # cycle = 0, initial cycle
860  fgcmPars = fgcm.FgcmParameters.newParsWithArrays(fgcmFitCycle.fgcmConfig,
861  fgcmLut,
862  fgcmExpInfo)
863  else:
864  inParInfo, inParams, inSuperStar = self._loadParameters(butler)
865  fgcmPars = fgcm.FgcmParameters.loadParsWithArrays(fgcmFitCycle.fgcmConfig,
866  fgcmExpInfo,
867  inParInfo,
868  inParams,
869  inSuperStar)
870 
871  lastCycle = configDict['cycleNumber'] - 1
872 
873  # set up the stars...
874  fgcmStars = fgcm.FgcmStars(fgcmFitCycle.fgcmConfig)
875 
876  starObs = butler.get('fgcmStarObservations')
877  starIds = butler.get('fgcmStarIds')
878  starIndices = butler.get('fgcmStarIndices')
879 
880  # grab the flagged stars if available
881  if butler.datasetExists('fgcmFlaggedStars', fgcmcycle=lastCycle):
882  flaggedStars = butler.get('fgcmFlaggedStars', fgcmcycle=lastCycle)
883  flagId = flaggedStars['objId'][:]
884  flagFlag = flaggedStars['objFlag'][:]
885  else:
886  flaggedStars = None
887  flagId = None
888  flagFlag = None
889 
890  if self.config.doReferenceCalibration:
891  refStars = butler.get('fgcmReferenceStars')
892 
893  refMag, refMagErr = extractReferenceMags(refStars,
894  self.config.bands,
895  self.config.filterMap)
896  refId = refStars['fgcm_id'][:]
897  else:
898  refStars = None
899  refId = None
900  refMag = None
901  refMagErr = None
902 
903  # match star observations to visits
904  # Only those star observations that match visits from fgcmExpInfo['VISIT'] will
905  # actually be transferred into fgcm using the indexing below.
906  visitIndex = np.searchsorted(fgcmExpInfo['VISIT'], starObs['visit'][starIndices['obsIndex']])
907 
908  # The fgcmStars.loadStars method will copy all the star information into
909  # special shared memory objects that will not blow up the memory usage when
910  # used with python multiprocessing. Once all the numbers are copied,
911  # it is necessary to release all references to the objects that previously
912  # stored the data to ensure that the garbage collector can clear the memory,
913  # and ensure that this memory is not copied when multiprocessing kicks in.
914 
915  # We determine the conversion from the native units (typically radians) to
916  # degrees for the first star. This allows us to treat coord_ra/coord_dec as
917  # numpy arrays rather than Angles, which would we approximately 600x slower.
918  conv = starObs[0]['ra'].asDegrees() / float(starObs[0]['ra'])
919 
920  fgcmStars.loadStars(fgcmPars,
921  starObs['visit'][starIndices['obsIndex']],
922  starObs['ccd'][starIndices['obsIndex']],
923  starObs['ra'][starIndices['obsIndex']] * conv,
924  starObs['dec'][starIndices['obsIndex']] * conv,
925  starObs['instMag'][starIndices['obsIndex']],
926  starObs['instMagErr'][starIndices['obsIndex']],
927  fgcmExpInfo['FILTERNAME'][visitIndex],
928  starIds['fgcm_id'][:],
929  starIds['ra'][:],
930  starIds['dec'][:],
931  starIds['obsArrIndex'][:],
932  starIds['nObs'][:],
933  obsX=starObs['x'][starIndices['obsIndex']],
934  obsY=starObs['y'][starIndices['obsIndex']],
935  obsDeltaMagBkg=starObs['deltaMagBkg'][starIndices['obsIndex']],
936  psfCandidate=starObs['psf_candidate'][starIndices['obsIndex']],
937  refID=refId,
938  refMag=refMag,
939  refMagErr=refMagErr,
940  flagID=flagId,
941  flagFlag=flagFlag,
942  computeNobs=True)
943 
944  # Release all references to temporary objects holding star data (see above)
945  del starObs
946  del starIds
947  del starIndices
948  del flagId
949  del flagFlag
950  del flaggedStars
951  del refStars
952  del refId
953  del refMag
954  del refMagErr
955 
956  # and set the bits in the cycle object
957  fgcmFitCycle.setLUT(fgcmLut)
958  fgcmFitCycle.setStars(fgcmStars, fgcmPars)
959  fgcmFitCycle.setPars(fgcmPars)
960 
961  # finish the setup
962  fgcmFitCycle.finishSetup()
963 
964  # and run
965  fgcmFitCycle.run()
966 
967 
970 
971  self._persistFgcmDatasets(butler, fgcmFitCycle)
972 
973  # Output the config for the next cycle
974  # We need to make a copy since the input one has been frozen
975 
976  updatedPhotometricCutDict = {b: float(fgcmFitCycle.updatedPhotometricCut[i]) for
977  i, b in enumerate(self.config.bands)}
978  updatedHighCutDict = {band: float(fgcmFitCycle.updatedHighCut[i]) for
979  i, band in enumerate(self.config.bands)}
980 
981  outConfig = copy.copy(self.config)
982  outConfig.update(cycleNumber=(self.config.cycleNumber + 1),
983  precomputeSuperStarInitialCycle=False,
984  freezeStdAtmosphere=False,
985  expGrayPhotometricCutDict=updatedPhotometricCutDict,
986  expGrayHighCutDict=updatedHighCutDict)
987  configFileName = '%s_cycle%02d_config.py' % (outConfig.outfileBase,
988  outConfig.cycleNumber)
989  outConfig.save(configFileName)
990 
991  if self.config.isFinalCycle == 1:
992  # We are done, ready to output products
993  self.log.info("Everything is in place to run fgcmOutputProducts.py")
994  else:
995  self.log.info("Saved config for next cycle to %s" % (configFileName))
996  self.log.info("Be sure to look at:")
997  self.log.info(" config.expGrayPhotometricCut")
998  self.log.info(" config.expGrayHighCut")
999  self.log.info("If you are satisfied with the fit, please set:")
1000  self.log.info(" config.isFinalCycle = True")
1001 
1002  def _checkDatasetsExist(self, butler):
1003  """
1004  Check if necessary datasets exist to run fgcmFitCycle
1005 
1006  Parameters
1007  ----------
1008  butler: `lsst.daf.persistence.Butler`
1009 
1010  Raises
1011  ------
1012  RuntimeError
1013  If any of fgcmVisitCatalog, fgcmStarObservations, fgcmStarIds,
1014  fgcmStarIndices, fgcmLookUpTable datasets do not exist.
1015  If cycleNumber > 0, then also checks for fgcmFitParameters,
1016  fgcmFlaggedStars.
1017  """
1018 
1019  if not butler.datasetExists('fgcmVisitCatalog'):
1020  raise RuntimeError("Could not find fgcmVisitCatalog in repo!")
1021  if not butler.datasetExists('fgcmStarObservations'):
1022  raise RuntimeError("Could not find fgcmStarObservations in repo!")
1023  if not butler.datasetExists('fgcmStarIds'):
1024  raise RuntimeError("Could not find fgcmStarIds in repo!")
1025  if not butler.datasetExists('fgcmStarIndices'):
1026  raise RuntimeError("Could not find fgcmStarIndices in repo!")
1027  if not butler.datasetExists('fgcmLookUpTable'):
1028  raise RuntimeError("Could not find fgcmLookUpTable in repo!")
1029 
1030  # Need additional datasets if we are not the initial cycle
1031  if (self.config.cycleNumber > 0):
1032  if not butler.datasetExists('fgcmFitParameters',
1033  fgcmcycle=self.config.cycleNumber-1):
1034  raise RuntimeError("Could not find fgcmFitParameters for previous cycle (%d) in repo!" %
1035  (self.config.cycleNumber-1))
1036  if not butler.datasetExists('fgcmFlaggedStars',
1037  fgcmcycle=self.config.cycleNumber-1):
1038  raise RuntimeError("Could not find fgcmFlaggedStars for previous cycle (%d) in repo!" %
1039  (self.config.cycleNumber-1))
1040 
1041  # And additional dataset if we want reference calibration
1042  if self.config.doReferenceCalibration:
1043  if not butler.datasetExists('fgcmReferenceStars'):
1044  raise RuntimeError("Could not find fgcmReferenceStars in repo, and "
1045  "doReferenceCalibration is True.")
1046 
1047  def _loadParameters(self, butler):
1048  """
1049  Load FGCM parameters from a previous fit cycle
1050 
1051  Parameters
1052  ----------
1053  butler: `lsst.daf.persistence.Butler`
1054 
1055  Returns
1056  -------
1057  inParInfo: `numpy.ndarray`
1058  Numpy array parameter information formatted for input to fgcm
1059  inParameters: `numpy.ndarray`
1060  Numpy array parameter values formatted for input to fgcm
1061  inSuperStar: `numpy.array`
1062  Superstar flat formatted for input to fgcm
1063  """
1064 
1065  # note that we already checked that this is available
1066  parCat = butler.get('fgcmFitParameters', fgcmcycle=self.config.cycleNumber-1)
1067 
1068  parLutFilterNames = np.array(parCat[0]['lutFilterNames'].split(','))
1069  parFitBands = np.array(parCat[0]['fitBands'].split(','))
1070 
1071  inParInfo = np.zeros(1, dtype=[('NCCD', 'i4'),
1072  ('LUTFILTERNAMES', parLutFilterNames.dtype.str,
1073  (parLutFilterNames.size, )),
1074  ('FITBANDS', parFitBands.dtype.str, (parFitBands.size, )),
1075  ('LNTAUUNIT', 'f8'),
1076  ('LNTAUSLOPEUNIT', 'f8'),
1077  ('ALPHAUNIT', 'f8'),
1078  ('LNPWVUNIT', 'f8'),
1079  ('LNPWVSLOPEUNIT', 'f8'),
1080  ('LNPWVQUADRATICUNIT', 'f8'),
1081  ('LNPWVGLOBALUNIT', 'f8'),
1082  ('O3UNIT', 'f8'),
1083  ('QESYSUNIT', 'f8'),
1084  ('FILTEROFFSETUNIT', 'f8'),
1085  ('HASEXTERNALPWV', 'i2'),
1086  ('HASEXTERNALTAU', 'i2')])
1087  inParInfo['NCCD'] = parCat['nCcd']
1088  inParInfo['LUTFILTERNAMES'][:] = parLutFilterNames
1089  inParInfo['FITBANDS'][:] = parFitBands
1090  inParInfo['HASEXTERNALPWV'] = parCat['hasExternalPwv']
1091  inParInfo['HASEXTERNALTAU'] = parCat['hasExternalTau']
1092 
1093  inParams = np.zeros(1, dtype=[('PARALPHA', 'f8', (parCat['parAlpha'].size, )),
1094  ('PARO3', 'f8', (parCat['parO3'].size, )),
1095  ('PARLNTAUINTERCEPT', 'f8',
1096  (parCat['parLnTauIntercept'].size, )),
1097  ('PARLNTAUSLOPE', 'f8',
1098  (parCat['parLnTauSlope'].size, )),
1099  ('PARLNPWVINTERCEPT', 'f8',
1100  (parCat['parLnPwvIntercept'].size, )),
1101  ('PARLNPWVSLOPE', 'f8',
1102  (parCat['parLnPwvSlope'].size, )),
1103  ('PARLNPWVQUADRATIC', 'f8',
1104  (parCat['parLnPwvQuadratic'].size, )),
1105  ('PARQESYSINTERCEPT', 'f8',
1106  (parCat['parQeSysIntercept'].size, )),
1107  ('COMPQESYSSLOPE', 'f8',
1108  (parCat['compQeSysSlope'].size, )),
1109  ('PARFILTEROFFSET', 'f8',
1110  (parCat['parFilterOffset'].size, )),
1111  ('PARFILTEROFFSETFITFLAG', 'i2',
1112  (parCat['parFilterOffsetFitFlag'].size, )),
1113  ('PARRETRIEVEDLNPWVSCALE', 'f8'),
1114  ('PARRETRIEVEDLNPWVOFFSET', 'f8'),
1115  ('PARRETRIEVEDLNPWVNIGHTLYOFFSET', 'f8',
1116  (parCat['parRetrievedLnPwvNightlyOffset'].size, )),
1117  ('COMPABSTHROUGHPUT', 'f8',
1118  (parCat['compAbsThroughput'].size, )),
1119  ('COMPREFOFFSET', 'f8',
1120  (parCat['compRefOffset'].size, )),
1121  ('COMPREFSIGMA', 'f8',
1122  (parCat['compRefSigma'].size, )),
1123  ('COMPMIRRORCHROMATICITY', 'f8',
1124  (parCat['compMirrorChromaticity'].size, )),
1125  ('MIRRORCHROMATICITYPIVOT', 'f8',
1126  (parCat['mirrorChromaticityPivot'].size, )),
1127  ('COMPMEDIANSEDSLOPE', 'f8',
1128  (parCat['compMedianSedSlope'].size, )),
1129  ('COMPAPERCORRPIVOT', 'f8',
1130  (parCat['compAperCorrPivot'].size, )),
1131  ('COMPAPERCORRSLOPE', 'f8',
1132  (parCat['compAperCorrSlope'].size, )),
1133  ('COMPAPERCORRSLOPEERR', 'f8',
1134  (parCat['compAperCorrSlopeErr'].size, )),
1135  ('COMPAPERCORRRANGE', 'f8',
1136  (parCat['compAperCorrRange'].size, )),
1137  ('COMPMODELERREXPTIMEPIVOT', 'f8',
1138  (parCat['compModelErrExptimePivot'].size, )),
1139  ('COMPMODELERRFWHMPIVOT', 'f8',
1140  (parCat['compModelErrFwhmPivot'].size, )),
1141  ('COMPMODELERRSKYPIVOT', 'f8',
1142  (parCat['compModelErrSkyPivot'].size, )),
1143  ('COMPMODELERRPARS', 'f8',
1144  (parCat['compModelErrPars'].size, )),
1145  ('COMPEXPGRAY', 'f8',
1146  (parCat['compExpGray'].size, )),
1147  ('COMPVARGRAY', 'f8',
1148  (parCat['compVarGray'].size, )),
1149  ('COMPEXPDELTAMAGBKG', 'f8',
1150  (parCat['compExpDeltaMagBkg'].size, )),
1151  ('COMPNGOODSTARPEREXP', 'i4',
1152  (parCat['compNGoodStarPerExp'].size, )),
1153  ('COMPSIGFGCM', 'f8',
1154  (parCat['compSigFgcm'].size, )),
1155  ('COMPSIGMACAL', 'f8',
1156  (parCat['compSigmaCal'].size, )),
1157  ('COMPRETRIEVEDLNPWV', 'f8',
1158  (parCat['compRetrievedLnPwv'].size, )),
1159  ('COMPRETRIEVEDLNPWVRAW', 'f8',
1160  (parCat['compRetrievedLnPwvRaw'].size, )),
1161  ('COMPRETRIEVEDLNPWVFLAG', 'i2',
1162  (parCat['compRetrievedLnPwvFlag'].size, )),
1163  ('COMPRETRIEVEDTAUNIGHT', 'f8',
1164  (parCat['compRetrievedTauNight'].size, ))])
1165 
1166  inParams['PARALPHA'][:] = parCat['parAlpha'][0, :]
1167  inParams['PARO3'][:] = parCat['parO3'][0, :]
1168  inParams['PARLNTAUINTERCEPT'][:] = parCat['parLnTauIntercept'][0, :]
1169  inParams['PARLNTAUSLOPE'][:] = parCat['parLnTauSlope'][0, :]
1170  inParams['PARLNPWVINTERCEPT'][:] = parCat['parLnPwvIntercept'][0, :]
1171  inParams['PARLNPWVSLOPE'][:] = parCat['parLnPwvSlope'][0, :]
1172  inParams['PARLNPWVQUADRATIC'][:] = parCat['parLnPwvQuadratic'][0, :]
1173  inParams['PARQESYSINTERCEPT'][:] = parCat['parQeSysIntercept'][0, :]
1174  inParams['COMPQESYSSLOPE'][:] = parCat['compQeSysSlope'][0, :]
1175  inParams['PARFILTEROFFSET'][:] = parCat['parFilterOffset'][0, :]
1176  inParams['PARFILTEROFFSETFITFLAG'][:] = parCat['parFilterOffsetFitFlag'][0, :]
1177  inParams['PARRETRIEVEDLNPWVSCALE'] = parCat['parRetrievedLnPwvScale']
1178  inParams['PARRETRIEVEDLNPWVOFFSET'] = parCat['parRetrievedLnPwvOffset']
1179  inParams['PARRETRIEVEDLNPWVNIGHTLYOFFSET'][:] = parCat['parRetrievedLnPwvNightlyOffset'][0, :]
1180  inParams['COMPABSTHROUGHPUT'][:] = parCat['compAbsThroughput'][0, :]
1181  inParams['COMPREFOFFSET'][:] = parCat['compRefOffset'][0, :]
1182  inParams['COMPREFSIGMA'][:] = parCat['compRefSigma'][0, :]
1183  inParams['COMPMIRRORCHROMATICITY'][:] = parCat['compMirrorChromaticity'][0, :]
1184  inParams['MIRRORCHROMATICITYPIVOT'][:] = parCat['mirrorChromaticityPivot'][0, :]
1185  inParams['COMPMEDIANSEDSLOPE'][:] = parCat['compMedianSedSlope'][0, :]
1186  inParams['COMPAPERCORRPIVOT'][:] = parCat['compAperCorrPivot'][0, :]
1187  inParams['COMPAPERCORRSLOPE'][:] = parCat['compAperCorrSlope'][0, :]
1188  inParams['COMPAPERCORRSLOPEERR'][:] = parCat['compAperCorrSlopeErr'][0, :]
1189  inParams['COMPAPERCORRRANGE'][:] = parCat['compAperCorrRange'][0, :]
1190  inParams['COMPMODELERREXPTIMEPIVOT'][:] = parCat['compModelErrExptimePivot'][0, :]
1191  inParams['COMPMODELERRFWHMPIVOT'][:] = parCat['compModelErrFwhmPivot'][0, :]
1192  inParams['COMPMODELERRSKYPIVOT'][:] = parCat['compModelErrSkyPivot'][0, :]
1193  inParams['COMPMODELERRPARS'][:] = parCat['compModelErrPars'][0, :]
1194  inParams['COMPEXPGRAY'][:] = parCat['compExpGray'][0, :]
1195  inParams['COMPVARGRAY'][:] = parCat['compVarGray'][0, :]
1196  inParams['COMPEXPDELTAMAGBKG'][:] = parCat['compExpDeltaMagBkg'][0, :]
1197  inParams['COMPNGOODSTARPEREXP'][:] = parCat['compNGoodStarPerExp'][0, :]
1198  inParams['COMPSIGFGCM'][:] = parCat['compSigFgcm'][0, :]
1199  inParams['COMPSIGMACAL'][:] = parCat['compSigmaCal'][0, :]
1200  inParams['COMPRETRIEVEDLNPWV'][:] = parCat['compRetrievedLnPwv'][0, :]
1201  inParams['COMPRETRIEVEDLNPWVRAW'][:] = parCat['compRetrievedLnPwvRaw'][0, :]
1202  inParams['COMPRETRIEVEDLNPWVFLAG'][:] = parCat['compRetrievedLnPwvFlag'][0, :]
1203  inParams['COMPRETRIEVEDTAUNIGHT'][:] = parCat['compRetrievedTauNight'][0, :]
1204 
1205  inSuperStar = np.zeros(parCat['superstarSize'][0, :], dtype='f8')
1206  inSuperStar[:, :, :, :] = parCat['superstar'][0, :].reshape(inSuperStar.shape)
1207 
1208  return (inParInfo, inParams, inSuperStar)
1209 
1210  def _persistFgcmDatasets(self, butler, fgcmFitCycle):
1211  """
1212  Persist FGCM datasets through the butler.
1213 
1214  Parameters
1215  ----------
1216  butler: `lsst.daf.persistence.Butler`
1217  fgcmFitCycle: `lsst.fgcm.FgcmFitCycle`
1218  Fgcm Fit cycle object
1219  """
1220 
1221  # Save the parameters
1222  parInfo, pars = fgcmFitCycle.fgcmPars.parsToArrays()
1223 
1224  parSchema = afwTable.Schema()
1225 
1226  comma = ','
1227  lutFilterNameString = comma.join([n.decode('utf-8')
1228  for n in parInfo['LUTFILTERNAMES'][0]])
1229  fitBandString = comma.join([n.decode('utf-8')
1230  for n in parInfo['FITBANDS'][0]])
1231 
1232  parSchema = self._makeParSchema(parInfo, pars, fgcmFitCycle.fgcmPars.parSuperStarFlat,
1233  lutFilterNameString, fitBandString)
1234  parCat = self._makeParCatalog(parSchema, parInfo, pars,
1235  fgcmFitCycle.fgcmPars.parSuperStarFlat,
1236  lutFilterNameString, fitBandString)
1237 
1238  butler.put(parCat, 'fgcmFitParameters', fgcmcycle=self.config.cycleNumber)
1239 
1240  # Save the indices of the flagged stars
1241  # (stars that have been (a) reserved from the fit for testing and
1242  # (b) bad stars that have failed quality checks.)
1243  flagStarSchema = self._makeFlagStarSchema()
1244  flagStarStruct = fgcmFitCycle.fgcmStars.getFlagStarIndices()
1245  flagStarCat = self._makeFlagStarCat(flagStarSchema, flagStarStruct)
1246 
1247  butler.put(flagStarCat, 'fgcmFlaggedStars', fgcmcycle=self.config.cycleNumber)
1248 
1249  # Save the zeropoint information and atmospheres only if desired
1250  if self.outputZeropoints:
1251  superStarChebSize = fgcmFitCycle.fgcmZpts.zpStruct['FGCM_FZPT_SSTAR_CHEB'].shape[1]
1252  zptChebSize = fgcmFitCycle.fgcmZpts.zpStruct['FGCM_FZPT_CHEB'].shape[1]
1253 
1254  zptSchema = makeZptSchema(superStarChebSize, zptChebSize)
1255  zptCat = makeZptCat(zptSchema, fgcmFitCycle.fgcmZpts.zpStruct)
1256 
1257  butler.put(zptCat, 'fgcmZeropoints', fgcmcycle=self.config.cycleNumber)
1258 
1259  # Save atmosphere values
1260  # These are generated by the same code that generates zeropoints
1261  atmSchema = makeAtmSchema()
1262  atmCat = makeAtmCat(atmSchema, fgcmFitCycle.fgcmZpts.atmStruct)
1263 
1264  butler.put(atmCat, 'fgcmAtmosphereParameters', fgcmcycle=self.config.cycleNumber)
1265 
1266  # Save the standard stars (if configured)
1267  if self.outputStandards:
1268  stdStruct, goodBands = fgcmFitCycle.fgcmStars.retrieveStdStarCatalog(fgcmFitCycle.fgcmPars)
1269  stdSchema = makeStdSchema(len(goodBands))
1270  stdCat = makeStdCat(stdSchema, stdStruct, goodBands)
1271 
1272  butler.put(stdCat, 'fgcmStandardStars', fgcmcycle=self.config.cycleNumber)
1273 
1274  def _makeParSchema(self, parInfo, pars, parSuperStarFlat,
1275  lutFilterNameString, fitBandString):
1276  """
1277  Make the parameter persistence schema
1278 
1279  Parameters
1280  ----------
1281  parInfo: `numpy.ndarray`
1282  Parameter information returned by fgcm
1283  pars: `numpy.ndarray`
1284  Parameter values returned by fgcm
1285  parSuperStarFlat: `numpy.array`
1286  Superstar flat values returned by fgcm
1287  lutFilterNameString: `str`
1288  Combined string of all the lutFilterNames
1289  fitBandString: `str`
1290  Combined string of all the fitBands
1291 
1292  Returns
1293  -------
1294  parSchema: `afwTable.schema`
1295  """
1296 
1297  parSchema = afwTable.Schema()
1298 
1299  # parameter info section
1300  parSchema.addField('nCcd', type=np.int32, doc='Number of CCDs')
1301  parSchema.addField('lutFilterNames', type=str, doc='LUT Filter names in parameter file',
1302  size=len(lutFilterNameString))
1303  parSchema.addField('fitBands', type=str, doc='Bands that were fit',
1304  size=len(fitBandString))
1305  parSchema.addField('lnTauUnit', type=np.float64, doc='Step units for ln(AOD)')
1306  parSchema.addField('lnTauSlopeUnit', type=np.float64,
1307  doc='Step units for ln(AOD) slope')
1308  parSchema.addField('alphaUnit', type=np.float64, doc='Step units for alpha')
1309  parSchema.addField('lnPwvUnit', type=np.float64, doc='Step units for ln(pwv)')
1310  parSchema.addField('lnPwvSlopeUnit', type=np.float64,
1311  doc='Step units for ln(pwv) slope')
1312  parSchema.addField('lnPwvQuadraticUnit', type=np.float64,
1313  doc='Step units for ln(pwv) quadratic term')
1314  parSchema.addField('lnPwvGlobalUnit', type=np.float64,
1315  doc='Step units for global ln(pwv) parameters')
1316  parSchema.addField('o3Unit', type=np.float64, doc='Step units for O3')
1317  parSchema.addField('qeSysUnit', type=np.float64, doc='Step units for mirror gray')
1318  parSchema.addField('filterOffsetUnit', type=np.float64, doc='Step units for filter offset')
1319  parSchema.addField('hasExternalPwv', type=np.int32, doc='Parameters fit using external pwv')
1320  parSchema.addField('hasExternalTau', type=np.int32, doc='Parameters fit using external tau')
1321 
1322  # parameter section
1323  parSchema.addField('parAlpha', type='ArrayD', doc='Alpha parameter vector',
1324  size=pars['PARALPHA'].size)
1325  parSchema.addField('parO3', type='ArrayD', doc='O3 parameter vector',
1326  size=pars['PARO3'].size)
1327  parSchema.addField('parLnTauIntercept', type='ArrayD',
1328  doc='ln(Tau) intercept parameter vector',
1329  size=pars['PARLNTAUINTERCEPT'].size)
1330  parSchema.addField('parLnTauSlope', type='ArrayD',
1331  doc='ln(Tau) slope parameter vector',
1332  size=pars['PARLNTAUSLOPE'].size)
1333  parSchema.addField('parLnPwvIntercept', type='ArrayD', doc='ln(pwv) intercept parameter vector',
1334  size=pars['PARLNPWVINTERCEPT'].size)
1335  parSchema.addField('parLnPwvSlope', type='ArrayD', doc='ln(pwv) slope parameter vector',
1336  size=pars['PARLNPWVSLOPE'].size)
1337  parSchema.addField('parLnPwvQuadratic', type='ArrayD', doc='ln(pwv) quadratic parameter vector',
1338  size=pars['PARLNPWVQUADRATIC'].size)
1339  parSchema.addField('parQeSysIntercept', type='ArrayD', doc='Mirror gray intercept parameter vector',
1340  size=pars['PARQESYSINTERCEPT'].size)
1341  parSchema.addField('compQeSysSlope', type='ArrayD', doc='Mirror gray slope parameter vector',
1342  size=pars[0]['COMPQESYSSLOPE'].size)
1343  parSchema.addField('parFilterOffset', type='ArrayD', doc='Filter offset parameter vector',
1344  size=pars['PARFILTEROFFSET'].size)
1345  parSchema.addField('parFilterOffsetFitFlag', type='ArrayI', doc='Filter offset parameter fit flag',
1346  size=pars['PARFILTEROFFSETFITFLAG'].size)
1347  parSchema.addField('parRetrievedLnPwvScale', type=np.float64,
1348  doc='Global scale for retrieved ln(pwv)')
1349  parSchema.addField('parRetrievedLnPwvOffset', type=np.float64,
1350  doc='Global offset for retrieved ln(pwv)')
1351  parSchema.addField('parRetrievedLnPwvNightlyOffset', type='ArrayD',
1352  doc='Nightly offset for retrieved ln(pwv)',
1353  size=pars['PARRETRIEVEDLNPWVNIGHTLYOFFSET'].size)
1354  parSchema.addField('compAbsThroughput', type='ArrayD',
1355  doc='Absolute throughput (relative to transmission curves)',
1356  size=pars['COMPABSTHROUGHPUT'].size)
1357  parSchema.addField('compRefOffset', type='ArrayD',
1358  doc='Offset between reference stars and calibrated stars',
1359  size=pars['COMPREFOFFSET'].size)
1360  parSchema.addField('compRefSigma', type='ArrayD',
1361  doc='Width of reference star/calibrated star distribution',
1362  size=pars['COMPREFSIGMA'].size)
1363  parSchema.addField('compMirrorChromaticity', type='ArrayD',
1364  doc='Computed mirror chromaticity terms',
1365  size=pars['COMPMIRRORCHROMATICITY'].size)
1366  parSchema.addField('mirrorChromaticityPivot', type='ArrayD',
1367  doc='Mirror chromaticity pivot mjd',
1368  size=pars['MIRRORCHROMATICITYPIVOT'].size)
1369  parSchema.addField('compMedianSedSlope', type='ArrayD',
1370  doc='Computed median SED slope (per band)',
1371  size=pars['COMPMEDIANSEDSLOPE'].size)
1372  parSchema.addField('compAperCorrPivot', type='ArrayD', doc='Aperture correction pivot',
1373  size=pars['COMPAPERCORRPIVOT'].size)
1374  parSchema.addField('compAperCorrSlope', type='ArrayD', doc='Aperture correction slope',
1375  size=pars['COMPAPERCORRSLOPE'].size)
1376  parSchema.addField('compAperCorrSlopeErr', type='ArrayD', doc='Aperture correction slope error',
1377  size=pars['COMPAPERCORRSLOPEERR'].size)
1378  parSchema.addField('compAperCorrRange', type='ArrayD', doc='Aperture correction range',
1379  size=pars['COMPAPERCORRRANGE'].size)
1380  parSchema.addField('compModelErrExptimePivot', type='ArrayD', doc='Model error exptime pivot',
1381  size=pars['COMPMODELERREXPTIMEPIVOT'].size)
1382  parSchema.addField('compModelErrFwhmPivot', type='ArrayD', doc='Model error fwhm pivot',
1383  size=pars['COMPMODELERRFWHMPIVOT'].size)
1384  parSchema.addField('compModelErrSkyPivot', type='ArrayD', doc='Model error sky pivot',
1385  size=pars['COMPMODELERRSKYPIVOT'].size)
1386  parSchema.addField('compModelErrPars', type='ArrayD', doc='Model error parameters',
1387  size=pars['COMPMODELERRPARS'].size)
1388  parSchema.addField('compExpGray', type='ArrayD', doc='Computed exposure gray',
1389  size=pars['COMPEXPGRAY'].size)
1390  parSchema.addField('compVarGray', type='ArrayD', doc='Computed exposure variance',
1391  size=pars['COMPVARGRAY'].size)
1392  parSchema.addField('compExpDeltaMagBkg', type='ArrayD',
1393  doc='Computed exposure offset due to background',
1394  size=pars['COMPEXPDELTAMAGBKG'].size)
1395  parSchema.addField('compNGoodStarPerExp', type='ArrayI',
1396  doc='Computed number of good stars per exposure',
1397  size=pars['COMPNGOODSTARPEREXP'].size)
1398  parSchema.addField('compSigFgcm', type='ArrayD', doc='Computed sigma_fgcm (intrinsic repeatability)',
1399  size=pars['COMPSIGFGCM'].size)
1400  parSchema.addField('compSigmaCal', type='ArrayD', doc='Computed sigma_cal (systematic error floor)',
1401  size=pars['COMPSIGMACAL'].size)
1402  parSchema.addField('compRetrievedLnPwv', type='ArrayD', doc='Retrieved ln(pwv) (smoothed)',
1403  size=pars['COMPRETRIEVEDLNPWV'].size)
1404  parSchema.addField('compRetrievedLnPwvRaw', type='ArrayD', doc='Retrieved ln(pwv) (raw)',
1405  size=pars['COMPRETRIEVEDLNPWVRAW'].size)
1406  parSchema.addField('compRetrievedLnPwvFlag', type='ArrayI', doc='Retrieved ln(pwv) Flag',
1407  size=pars['COMPRETRIEVEDLNPWVFLAG'].size)
1408  parSchema.addField('compRetrievedTauNight', type='ArrayD', doc='Retrieved tau (per night)',
1409  size=pars['COMPRETRIEVEDTAUNIGHT'].size)
1410  # superstarflat section
1411  parSchema.addField('superstarSize', type='ArrayI', doc='Superstar matrix size',
1412  size=4)
1413  parSchema.addField('superstar', type='ArrayD', doc='Superstar matrix (flattened)',
1414  size=parSuperStarFlat.size)
1415 
1416  return parSchema
1417 
1418  def _makeParCatalog(self, parSchema, parInfo, pars, parSuperStarFlat,
1419  lutFilterNameString, fitBandString):
1420  """
1421  Make the FGCM parameter catalog for persistence
1422 
1423  Parameters
1424  ----------
1425  parSchema: `lsst.afw.table.Schema`
1426  Parameter catalog schema
1427  pars: `numpy.ndarray`
1428  FGCM parameters to put into parCat
1429  parSuperStarFlat: `numpy.array`
1430  FGCM superstar flat array to put into parCat
1431  lutFilterNameString: `str`
1432  Combined string of all the lutFilterNames
1433  fitBandString: `str`
1434  Combined string of all the fitBands
1435 
1436  Returns
1437  -------
1438  parCat: `afwTable.BasicCatalog`
1439  Atmosphere and instrumental model parameter catalog for persistence
1440  """
1441 
1442  parCat = afwTable.BaseCatalog(parSchema)
1443  parCat.reserve(1)
1444 
1445  # The parameter catalog just has one row, with many columns for all the
1446  # atmosphere and instrument fit parameters
1447  rec = parCat.addNew()
1448 
1449  # info section
1450  rec['nCcd'] = parInfo['NCCD']
1451  rec['lutFilterNames'] = lutFilterNameString
1452  rec['fitBands'] = fitBandString
1453  # note these are not currently supported here.
1454  rec['hasExternalPwv'] = 0
1455  rec['hasExternalTau'] = 0
1456 
1457  # parameter section
1458 
1459  scalarNames = ['parRetrievedLnPwvScale', 'parRetrievedLnPwvOffset']
1460 
1461  arrNames = ['parAlpha', 'parO3', 'parLnTauIntercept', 'parLnTauSlope',
1462  'parLnPwvIntercept', 'parLnPwvSlope', 'parLnPwvQuadratic',
1463  'parQeSysIntercept', 'compQeSysSlope',
1464  'parRetrievedLnPwvNightlyOffset', 'compAperCorrPivot',
1465  'parFilterOffset', 'parFilterOffsetFitFlag',
1466  'compAbsThroughput', 'compRefOffset', 'compRefSigma',
1467  'compMirrorChromaticity', 'mirrorChromaticityPivot',
1468  'compAperCorrSlope', 'compAperCorrSlopeErr', 'compAperCorrRange',
1469  'compModelErrExptimePivot', 'compModelErrFwhmPivot',
1470  'compModelErrSkyPivot', 'compModelErrPars',
1471  'compExpGray', 'compVarGray', 'compNGoodStarPerExp', 'compSigFgcm',
1472  'compSigmaCal', 'compExpDeltaMagBkg', 'compMedianSedSlope',
1473  'compRetrievedLnPwv', 'compRetrievedLnPwvRaw', 'compRetrievedLnPwvFlag',
1474  'compRetrievedTauNight']
1475 
1476  for scalarName in scalarNames:
1477  rec[scalarName] = pars[scalarName.upper()]
1478 
1479  for arrName in arrNames:
1480  rec[arrName][:] = np.atleast_1d(pars[0][arrName.upper()])[:]
1481 
1482  # superstar section
1483  rec['superstarSize'][:] = parSuperStarFlat.shape
1484  rec['superstar'][:] = parSuperStarFlat.flatten()
1485 
1486  return parCat
1487 
1488  def _makeFlagStarSchema(self):
1489  """
1490  Make the flagged-stars schema
1491 
1492  Returns
1493  -------
1494  flagStarSchema: `lsst.afw.table.Schema`
1495  """
1496 
1497  flagStarSchema = afwTable.Schema()
1498 
1499  flagStarSchema.addField('objId', type=np.int32, doc='FGCM object id')
1500  flagStarSchema.addField('objFlag', type=np.int32, doc='FGCM object flag')
1501 
1502  return flagStarSchema
1503 
1504  def _makeFlagStarCat(self, flagStarSchema, flagStarStruct):
1505  """
1506  Make the flagged star catalog for persistence
1507 
1508  Parameters
1509  ----------
1510  flagStarSchema: `lsst.afw.table.Schema`
1511  Flagged star schema
1512  flagStarStruct: `numpy.ndarray`
1513  Flagged star structure from fgcm
1514 
1515  Returns
1516  -------
1517  flagStarCat: `lsst.afw.table.BaseCatalog`
1518  Flagged star catalog for persistence
1519  """
1520 
1521  flagStarCat = afwTable.BaseCatalog(flagStarSchema)
1522  flagStarCat.resize(flagStarStruct.size)
1523 
1524  flagStarCat['objId'][:] = flagStarStruct['OBJID']
1525  flagStarCat['objFlag'][:] = flagStarStruct['OBJFLAG']
1526 
1527  return flagStarCat
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask._makeParCatalog
def _makeParCatalog(self, parSchema, parInfo, pars, parSuperStarFlat, lutFilterNameString, fitBandString)
Definition: fgcmFitCycle.py:1418
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask._loadParameters
def _loadParameters(self, butler)
Definition: fgcmFitCycle.py:1047
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask.outputZeropoints
outputZeropoints
Definition: fgcmFitCycle.py:816
lsst.fgcmcal.utilities.computeCcdOffsets
def computeCcdOffsets(camera, defaultOrientation)
Definition: utilities.py:378
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask.__init__
def __init__(self, butler=None, **kwargs)
Definition: fgcmFitCycle.py:734
lsst.fgcmcal.utilities.makeZptCat
def makeZptCat(zptSchema, zpStruct)
Definition: utilities.py:605
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask._makeFlagStarSchema
def _makeFlagStarSchema(self)
Definition: fgcmFitCycle.py:1488
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleRunner
Definition: fgcmFitCycle.py:657
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask._checkDatasetsExist
def _checkDatasetsExist(self, butler)
Definition: fgcmFitCycle.py:1002
lsst.fgcmcal.utilities.makeStdCat
def makeStdCat(stdSchema, stdStruct, goodBands)
Definition: utilities.py:749
lsst.fgcmcal.utilities.makeConfigDict
def makeConfigDict(config, log, camera, maxIter, resetFitParameters, outputZeropoints, tract=None)
Definition: utilities.py:41
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask.writeConfig
def writeConfig(self, butler, clobber=False, doBackup=True)
Definition: fgcmFitCycle.py:761
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask.maxIter
maxIter
Definition: fgcmFitCycle.py:814
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleRunner.run
def run(self, parsedCmd)
Definition: fgcmFitCycle.py:706
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleConfig
Definition: fgcmFitCycle.py:57
lsst.fgcmcal.utilities.translateFgcmLut
def translateFgcmLut(lutCat, filterMap)
Definition: utilities.py:196
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleRunner.getTargetList
def getTargetList(parsedCmd)
Definition: fgcmFitCycle.py:669
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask.resetFitParameters
resetFitParameters
Definition: fgcmFitCycle.py:817
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask.runDataRef
def runDataRef(self, butler)
Definition: fgcmFitCycle.py:750
lsst.fgcmcal.utilities.translateVisitCatalog
def translateVisitCatalog(visitCat)
Definition: utilities.py:327
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask._persistFgcmDatasets
def _persistFgcmDatasets(self, butler, fgcmFitCycle)
Definition: fgcmFitCycle.py:1210
lsst.fgcmcal.utilities.makeStdSchema
def makeStdSchema(nBands)
Definition: utilities.py:717
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask._makeParSchema
def _makeParSchema(self, parInfo, pars, parSuperStarFlat, lutFilterNameString, fitBandString)
Definition: fgcmFitCycle.py:1274
lsst.fgcmcal.utilities.makeAtmSchema
def makeAtmSchema()
Definition: utilities.py:660
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask
Definition: fgcmFitCycle.py:725
lsst.fgcmcal.utilities.makeZptSchema
def makeZptSchema(superStarChebyshevSize, zptChebyshevSize)
Definition: utilities.py:519
lsst.fgcmcal.utilities.makeAtmCat
def makeAtmCat(atmSchema, atmStruct)
Definition: utilities.py:684
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask._fgcmFitCycle
def _fgcmFitCycle(self, butler)
Definition: fgcmFitCycle.py:802
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleConfig.validate
def validate(self)
Definition: fgcmFitCycle.py:607
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask.outputStandards
outputStandards
Definition: fgcmFitCycle.py:815
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleConfig.setDefaults
def setDefaults(self)
Definition: fgcmFitCycle.py:604
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleTask._makeFlagStarCat
def _makeFlagStarCat(self, flagStarSchema, flagStarStruct)
Definition: fgcmFitCycle.py:1504
lsst.fgcmcal.fgcmFitCycle.FgcmFitCycleRunner.__call__
def __call__(self, butler)
Definition: fgcmFitCycle.py:675
lsst.fgcmcal.utilities.extractReferenceMags
def extractReferenceMags(refStars, bands, filterMap)
Definition: utilities.py:856