23"""Build star observations for input to FGCM using sourceTable_visit.
25This task finds all the visits and sourceTable_visits in a repository (or a
26subset based on command line parameters) and extracts all the potential
27calibration stars for input into fgcm. This task additionally uses fgcm to
28match star observations into unique stars, and performs
as much cleaning of the
29input catalog
as possible.
35from smatch.matcher import Matcher
36from astropy.table import Table, vstack
38from fgcm.fgcmUtilities import objFlagDict
40import lsst.pex.config as pexConfig
41import lsst.pipe.base as pipeBase
42from lsst.pipe.base import connectionTypes
43from lsst.meas.algorithms import ReferenceObjectLoader, LoadReferenceObjectsConfig
44from lsst.pipe.tasks.reserveIsolatedStars import ReserveIsolatedStarsTask
46from .fgcmBuildStarsBase import FgcmBuildStarsConfigBase, FgcmBuildStarsBaseTask
47from .utilities import computeApproxPixelAreaFields, computeApertureRadiusFromName
48from .utilities import lookupStaticCalibrations
50__all__ = ["FgcmBuildFromIsolatedStarsConfig", "FgcmBuildFromIsolatedStarsTask"]
53class FgcmBuildFromIsolatedStarsConnections(pipeBase.PipelineTaskConnections,
54 dimensions=("instrument",),
56 camera = connectionTypes.PrerequisiteInput(
57 doc=
"Camera instrument",
59 storageClass=
"Camera",
60 dimensions=(
"instrument",),
61 lookupFunction=lookupStaticCalibrations,
64 fgcm_lookup_table = connectionTypes.PrerequisiteInput(
65 doc=(
"Atmosphere + instrument look-up-table for FGCM throughput and "
66 "chromatic corrections."),
67 name=
"fgcmLookUpTable",
68 storageClass=
"Catalog",
69 dimensions=(
"instrument",),
72 ref_cat = connectionTypes.PrerequisiteInput(
73 doc=
"Reference catalog to use for photometric calibration.",
75 storageClass=
"SimpleCatalog",
76 dimensions=(
"skypix",),
80 isolated_star_cats = pipeBase.connectionTypes.Input(
81 doc=(
"Catalog of isolated stars with average positions, number of associated "
82 "sources, and indexes to the isolated_star_sources catalogs."),
83 name=
"isolated_star_cat",
84 storageClass=
"ArrowAstropy",
85 dimensions=(
"instrument",
"tract",
"skymap"),
89 isolated_star_sources = pipeBase.connectionTypes.Input(
90 doc=(
"Catalog of isolated star sources with sourceIds, and indexes to the "
91 "isolated_star_cats catalogs."),
92 name=
"isolated_star_sources",
93 storageClass=
"ArrowAstropy",
94 dimensions=(
"instrument",
"tract",
"skymap"),
98 visit_summaries = connectionTypes.Input(
99 doc=(
"Per-visit consolidated exposure metadata. These catalogs use "
100 "detector id for the id and must be sorted for fast lookups of a "
103 storageClass=
"ExposureCatalog",
104 dimensions=(
"instrument",
"visit"),
108 fgcm_visit_catalog = connectionTypes.Output(
109 doc=
"Catalog of visit information for fgcm.",
110 name=
"fgcmVisitCatalog",
111 storageClass=
"Catalog",
112 dimensions=(
"instrument",),
114 fgcm_star_observations = connectionTypes.Output(
115 doc=
"Catalog of star observations for fgcm.",
116 name=
"fgcm_star_observations",
117 storageClass=
"ArrowAstropy",
118 dimensions=(
"instrument",),
120 fgcm_star_ids = connectionTypes.Output(
121 doc=
"Catalog of fgcm calibration star IDs.",
122 name=
"fgcm_star_ids",
123 storageClass=
"ArrowAstropy",
124 dimensions=(
"instrument",),
126 fgcm_reference_stars = connectionTypes.Output(
127 doc=
"Catalog of fgcm-matched reference stars.",
128 name=
"fgcm_reference_stars",
129 storageClass=
"ArrowAstropy",
130 dimensions=(
"instrument",),
136 if not config.doReferenceMatches:
137 self.prerequisiteInputs.remove(
"ref_cat")
138 self.prerequisiteInputs.remove(
"fgcm_lookup_table")
139 self.outputs.remove(
"fgcm_reference_stars")
142 return (
"isolated_star_cats",
"visit_summaries")
146 pipelineConnections=FgcmBuildFromIsolatedStarsConnections):
147 """Config for FgcmBuildFromIsolatedStarsTask."""
148 referenceCCD = pexConfig.Field(
149 doc=
"Reference detector for checking PSF and background.",
153 reserve_selection = pexConfig.ConfigurableField(
154 target=ReserveIsolatedStarsTask,
155 doc=
"Task to select reserved stars.",
171 source_selector.setDefaults()
173 source_selector.doFlags =
False
174 source_selector.doSignalToNoise =
True
175 source_selector.doUnresolved =
False
176 source_selector.doIsolated =
False
177 source_selector.doRequireFiniteRaDec =
False
179 source_selector.flags.bad = []
181 source_selector.signalToNoise.minimum = 11.0
182 source_selector.signalToNoise.maximum = 1000.0
188 """Build star catalog for FGCM global calibration, using the isolated star catalogs.
190 ConfigClass = FgcmBuildFromIsolatedStarsConfig
191 _DefaultName = "fgcmBuildFromIsolatedStars"
193 canMultiprocess =
False
197 self.makeSubtask(
'reserve_selection')
200 input_ref_dict = butlerQC.get(inputRefs)
202 isolated_star_cat_handles = input_ref_dict[
"isolated_star_cats"]
203 isolated_star_source_handles = input_ref_dict[
"isolated_star_sources"]
205 isolated_star_cat_handle_dict = {
206 handle.dataId[
"tract"]: handle
for handle
in isolated_star_cat_handles
208 isolated_star_source_handle_dict = {
209 handle.dataId[
"tract"]: handle
for handle
in isolated_star_source_handles
212 if len(isolated_star_cat_handle_dict) != len(isolated_star_source_handle_dict):
213 raise RuntimeError(
"isolated_star_cats and isolate_star_sources must have same length.")
215 for tract
in isolated_star_cat_handle_dict:
216 if tract
not in isolated_star_source_handle_dict:
217 raise RuntimeError(f
"tract {tract} in isolated_star_cats but not isolated_star_sources")
219 if self.config.doReferenceMatches:
220 lookup_table_handle = input_ref_dict[
"fgcm_lookup_table"]
223 ref_config = LoadReferenceObjectsConfig()
224 ref_config.filterMap = self.config.fgcmLoadReferenceCatalog.filterMap
225 ref_obj_loader = ReferenceObjectLoader(dataIds=[ref.datasetRef.dataId
226 for ref
in inputRefs.ref_cat],
227 refCats=butlerQC.get(inputRefs.ref_cat),
228 name=self.config.connections.ref_cat,
231 self.makeSubtask(
'fgcmLoadReferenceCatalog',
232 refObjLoader=ref_obj_loader,
233 refCatName=self.config.connections.ref_cat)
235 lookup_table_handle =
None
241 visit_summary_handle_dict = {handle.dataId[
'visit']: [handle,
None]
for
242 handle
in input_ref_dict[
'visit_summaries']}
244 camera = input_ref_dict[
"camera"]
248 visit_summary_handle_dict=visit_summary_handle_dict,
249 isolated_star_cat_handle_dict=isolated_star_cat_handle_dict,
250 isolated_star_source_handle_dict=isolated_star_source_handle_dict,
251 lookup_table_handle=lookup_table_handle,
254 butlerQC.put(struct.fgcm_visit_catalog, outputRefs.fgcm_visit_catalog)
255 butlerQC.put(struct.fgcm_star_observations, outputRefs.fgcm_star_observations)
256 butlerQC.put(struct.fgcm_star_ids, outputRefs.fgcm_star_ids)
257 if self.config.doReferenceMatches:
258 butlerQC.put(struct.fgcm_reference_stars, outputRefs.fgcm_reference_stars)
260 def run(self, *, camera, visit_summary_handle_dict, isolated_star_cat_handle_dict,
261 isolated_star_source_handle_dict, lookup_table_handle=None):
262 """Run the fgcmBuildFromIsolatedStarsTask.
266 camera : `lsst.afw.cameraGeom.Camera`
268 visit_summary_handle_dict : `dict` [`int`, [`lsst.daf.butler.DeferredDatasetHandle`]]
269 Visit summary dataset handles, with the visit
as key.
270 isolated_star_cat_handle_dict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`]
271 Isolated star catalog dataset handles,
with the tract
as key.
272 isolated_star_source_handle_dict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`]
273 Isolated star source dataset handles,
with the tract
as key.
274 lookup_table_handle : `lsst.daf.butler.DeferredDatasetHandle`, optional
275 Data reference to fgcm look-up table (used
if matching reference stars).
279 struct : `lsst.pipe.base.struct`
280 Catalogs
for persistence,
with attributes:
282 ``fgcm_visit_catalog``
283 Catalog of per-visit data (`lsst.afw.table.ExposureCatalog`).
284 ``fgcm_star_observations``
285 Catalog of individual star observations (`astropy.table.Table`).
287 Catalog of per-star ids
and positions (`astropy.table.Table`).
288 ``fgcm_reference_stars``
289 Catalog of reference stars matched to fgcm stars (`astropy.table.Table`).
293 calib_flux_aperture_radius =
None
294 if self.config.doSubtractLocalBackground:
296 calib_flux_aperture_radius = computeApertureRadiusFromName(self.config.instFluxField)
297 except RuntimeError
as e:
298 raise RuntimeError(
"Could not determine aperture radius from %s. "
299 "Cannot use doSubtractLocalBackground." %
300 (self.config.instFluxField))
from e
303 if self.config.doReferenceMatches:
304 if lookup_table_handle
is None:
305 raise RuntimeError(
"Must supply lookup_table_handle if config.doReferenceMatches is True.")
311 isolated_star_cat_handle_dict,
312 isolated_star_source_handle_dict,
315 calib_flux_aperture_radius=calib_flux_aperture_radius,
330 if self.config.doReferenceMatches:
335 return pipeBase.Struct(
336 fgcm_visit_catalog=visit_cat,
337 fgcm_star_observations=star_obs,
338 fgcm_star_ids=fgcm_obj,
339 fgcm_reference_stars=fgcm_ref,
344 isolated_star_cat_handle_dict,
345 isolated_star_source_handle_dict,
348 calib_flux_aperture_radius=None,
350 """Make all star observations from isolated star catalogs.
354 isolated_star_cat_handle_dict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`]
355 Isolated star catalog dataset handles, with the tract
as key.
356 isolated_star_source_handle_dict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`]
357 Isolated star source dataset handles,
with the tract
as key.
358 visit_cat : `lsst.afw.table.ExposureCatalog`
359 Catalog of per-visit data.
360 camera : `lsst.afw.cameraGeom.Camera`
362 calib_flux_aperture_radius : `float`, optional
363 Radius
for the calibration flux aperture.
367 fgcm_obj : `astropy.table.Table`
368 Catalog of ids
and positions
for each star.
369 star_obs : `astropy.table.Table`
370 Catalog of individual star observations.
383 self.config.instFluxField,
384 self.config.instFluxField +
"Err",
385 self.config.apertureInnerInstFluxField,
386 self.config.apertureInnerInstFluxField +
"Err",
387 self.config.apertureOuterInstFluxField,
388 self.config.apertureOuterInstFluxField +
"Err",
391 if self.config.doSubtractLocalBackground:
392 source_columns.append(self.config.localBackgroundFluxField)
393 local_background_flag_name = self.config.localBackgroundFluxField[0: -len(
'instFlux')] +
'flag'
394 source_columns.append(local_background_flag_name)
396 if self.sourceSelector.config.doFlags:
397 source_columns.extend(self.sourceSelector.config.flags.bad)
399 local_background_area = np.pi*calib_flux_aperture_radius**2.
403 approx_pixel_area_fields = computeApproxPixelAreaFields(camera)
406 detector_mapping = {}
407 for detector_index, detector
in enumerate(camera):
408 detector_mapping[detector.getId()] = detector_index
418 (
"inst_mag_err",
"f4"),
420 (
"delta_mag_bkg",
"f4"),
421 (
"delta_mag_aper",
"f4"),
422 (
"delta_mag_err_aper",
"f4"),
427 (
"isolated_star_id",
"i8"),
430 (
"obs_arr_index",
"i4"),
437 merge_source_counter = 0
441 visit_cat_table = visit_cat.asAstropy()
443 for tract
in sorted(isolated_star_cat_handle_dict):
444 stars = isolated_star_cat_handle_dict[tract].get()
445 sources = isolated_star_source_handle_dict[tract].get(parameters={
"columns": source_columns})
448 good_sources = self.sourceSelector.selectSources(sources).selected
449 if self.config.doSubtractLocalBackground:
450 good_sources &= (~sources[local_background_flag_name])
451 local_background = local_background_area*sources[self.config.localBackgroundFluxField]
452 good_sources &= ((sources[self.config.instFluxField] - local_background) > 0)
454 if good_sources.sum() == 0:
455 self.log.info(
"No good sources found in tract %d", tract)
463 if len(self.config.requiredBands) > 0:
464 loop_bands = self.config.requiredBands
466 loop_bands = np.unique(sources[
"band"])
468 n_req = np.zeros((len(loop_bands), len(stars)), dtype=np.int32)
469 for i, band
in enumerate(loop_bands):
470 (band_use,) = (sources[good_sources][
"band"] == band).nonzero()
473 (i, sources[good_sources][
"obj_index"][band_use]),
477 if len(self.config.requiredBands) > 0:
480 (good_stars,) = (n_req.min(axis=0) >= self.config.minPerBand).nonzero()
484 (good_stars,) = (n_req.max(axis=0) >= self.config.minPerBand).nonzero()
488 obj_index = sources[
"obj_index"][good_sources]
489 a, b = esutil.numpy_util.match(good_stars, obj_index)
492 _, index_new = np.unique(a, return_index=
True)
493 stars[
"source_cat_index"][good_stars] = index_new
494 sources = sources[good_sources][b]
495 sources[
"obj_index"][:] = a
496 stars = stars[good_stars]
498 nsource = np.zeros(len(stars), dtype=np.int32)
501 sources[
"obj_index"],
504 stars[
"nsource"][:] = nsource
517 star_obs = Table(data=np.zeros(len(sources), dtype=star_obs_dtype))
518 star_obs[
"ra"] = sources[
"ra"]
519 star_obs[
"dec"] = sources[
"dec"]
520 star_obs[
"x"] = sources[
"x"]
521 star_obs[
"y"] = sources[
"y"]
522 star_obs[
"visit"] = sources[
"visit"]
523 star_obs[
"detector"] = sources[
"detector"]
525 visit_match, obs_match = esutil.numpy_util.match(visit_cat_table[
"visit"], sources[
"visit"])
527 exp_time = np.zeros(len(star_obs))
528 exp_time[obs_match] = visit_cat_table[
"exptime"][visit_match]
530 with warnings.catch_warnings():
532 warnings.simplefilter(
"ignore")
534 inst_mag_inner = -2.5*np.log10(sources[self.config.apertureInnerInstFluxField])
535 inst_mag_err_inner = k*(sources[self.config.apertureInnerInstFluxField +
"Err"]
536 / sources[self.config.apertureInnerInstFluxField])
537 inst_mag_outer = -2.5*np.log10(sources[self.config.apertureOuterInstFluxField])
538 inst_mag_err_outer = k*(sources[self.config.apertureOuterInstFluxField +
"Err"]
539 / sources[self.config.apertureOuterInstFluxField])
540 star_obs[
"delta_mag_aper"] = inst_mag_inner - inst_mag_outer
541 star_obs[
"delta_mag_err_aper"] = np.sqrt(inst_mag_err_inner**2. + inst_mag_err_outer**2.)
543 bad = ~np.isfinite(star_obs[
"delta_mag_aper"])
544 star_obs[
"delta_mag_aper"][bad] = 99.0
545 star_obs[
"delta_mag_err_aper"][bad] = 99.0
547 if self.config.doSubtractLocalBackground:
561 local_background = local_background_area*sources[self.config.localBackgroundFluxField]
562 star_obs[
"delta_mag_bkg"] = (-2.5*np.log10(sources[self.config.instFluxField]
563 - local_background) -
564 -2.5*np.log10(sources[self.config.instFluxField]))
567 for detector
in camera:
568 detector_id = detector.getId()
570 (use,) = (star_obs[
"detector"][obs_match] == detector_id).nonzero()
578 jac = approx_pixel_area_fields[detector_id].evaluate(
579 star_obs[
"x"][obs_match][use],
580 star_obs[
"y"][obs_match][use],
582 star_obs[
"jacobian"][obs_match[use]] = jac
583 scaled_inst_flux = (sources[self.config.instFluxField][obs_match[use]]
584 * visit_cat_table[
"scaling"][visit_match[use],
585 detector_mapping[detector_id]])
586 star_obs[
"inst_mag"][obs_match[use]] = (-2.5 * np.log10(scaled_inst_flux
590 star_obs[
"inst_mag_err"] = k*(sources[self.config.instFluxField +
"Err"]
591 / sources[self.config.instFluxField])
594 if self.config.doApplyWcsJacobian:
595 star_obs[
"inst_mag"] -= 2.5*np.log10(star_obs[
"jacobian"])
598 fgcm_obj = Table(data=np.zeros(len(stars), dtype=fgcm_obj_dtype))
599 fgcm_obj[
"isolated_star_id"] = stars[
"isolated_star_id"]
600 fgcm_obj[
"ra"] = stars[
"ra"]
601 fgcm_obj[
"dec"] = stars[
"dec"]
602 fgcm_obj[
"obs_arr_index"] = stars[
"source_cat_index"]
603 fgcm_obj[
"n_obs"] = stars[
"nsource"]
606 fgcm_obj[
"obs_arr_index"] += merge_source_counter
608 fgcm_objs.append(fgcm_obj)
609 star_obs_cats.append(star_obs)
611 merge_source_counter += len(star_obs)
613 fgcm_obj = vstack(fgcm_objs)
616 fgcm_obj[
"fgcm_id"][:] = np.arange(len(fgcm_obj)) + 1
618 return fgcm_obj, vstack(star_obs_cats)
621 """Downsample stars according to density.
623 Catalogs are modified in-place.
627 fgcm_obj : `astropy.table.Table`
628 Catalog of per-star ids
and positions.
629 star_obs : `astropy.table.Table`
630 Catalog of individual star observations.
632 if self.config.randomSeed
is not None:
633 np.random.seed(seed=self.config.randomSeed)
635 ipnest = hpg.angle_to_pixel(self.config.densityCutNside, fgcm_obj[
"ra"], fgcm_obj[
"dec"])
639 hist, rev_indices = esutil.stat.histogram(ipnest, rev=
True)
641 obj_use = np.ones(len(fgcm_obj), dtype=bool)
643 (high,) = (hist > self.config.densityCutMaxPerPixel).nonzero()
644 (ok,) = (hist > 0).nonzero()
645 self.log.info(
"There are %d/%d pixels with high stellar density.", high.size, ok.size)
646 for i
in range(high.size):
648 pix_indices = rev_indices[rev_indices[high[i]]: rev_indices[high[i] + 1]]
650 cut = np.random.choice(
652 size=pix_indices.size - self.config.densityCutMaxPerPixel,
657 fgcm_obj = fgcm_obj[obj_use]
659 obs_index = np.zeros(np.sum(fgcm_obj[
"n_obs"]), dtype=np.int32)
661 for i
in range(len(fgcm_obj)):
662 n_obs = fgcm_obj[
"n_obs"][i]
663 obs_index[ctr: ctr + n_obs] = (
664 np.arange(fgcm_obj[
"obs_arr_index"][i], fgcm_obj[
"obs_arr_index"][i] + n_obs)
666 fgcm_obj[
"obs_arr_index"][i] = ctr
669 star_obs = star_obs[obs_index]
672 """Run the star reservation task to flag reserved stars.
676 fgcm_obj : `astropy.table.Table`
677 Catalog of per-star ids and positions.
679 reserved = self.reserve_selection.run(
681 extra=','.join(self.config.requiredBands),
683 fgcm_obj[
"obj_flag"][reserved] |= objFlagDict[
"RESERVED"]
686 """Associate fgcm isolated stars with reference stars.
690 lookup_table_handle : `lsst.daf.butler.DeferredDatasetHandle`, optional
691 Data reference to fgcm look-up table (used if matching reference stars).
692 visit_cat : `lsst.afw.table.ExposureCatalog`
693 Catalog of per-visit data.
694 fgcm_obj : `astropy.table.Table`
695 Catalog of per-star ids
and positions
699 ref_cat : `astropy.table.Table`
700 Catalog of reference stars matched to fgcm stars.
703 lut_cat = lookup_table_handle.get()
705 std_filter_dict = {filter_name: std_filter
for (filter_name, std_filter)
in
706 zip(lut_cat[0][
"physicalFilters"].split(
","),
707 lut_cat[0][
"stdPhysicalFilters"].split(
","))}
708 std_lambda_dict = {std_filter: std_lambda
for (std_filter, std_lambda)
in
709 zip(lut_cat[0][
"stdPhysicalFilters"].split(
","),
710 lut_cat[0][
"lambdaStdFilter"])}
718 self.log.info(
"Using the following reference filters: %s", (
", ".join(reference_filter_names)))
721 ipnest = hpg.angle_to_pixel(self.config.coarseNside, fgcm_obj[
"ra"], fgcm_obj[
"dec"])
722 hpix, revpix = esutil.stat.histogram(ipnest, rev=
True)
727 dtype = [(
"fgcm_id",
"i4"),
728 (
"refMag",
"f4", (len(reference_filter_names), )),
729 (
"refMagErr",
"f4", (len(reference_filter_names), ))]
731 (gdpix,) = (hpix > 0).nonzero()
732 for ii, gpix
in enumerate(gdpix):
733 p1a = revpix[revpix[gpix]: revpix[gpix + 1]]
736 ra_wrap = fgcm_obj[
"ra"][p1a]
737 if (ra_wrap.min() < 10.0)
and (ra_wrap.max() > 350.0):
738 ra_wrap[ra_wrap > 180.0] -= 360.0
739 mean_ra = np.mean(ra_wrap) % 360.0
741 mean_ra = np.mean(ra_wrap)
742 mean_dec = np.mean(fgcm_obj[
"dec"][p1a])
744 dist = esutil.coords.sphdist(mean_ra, mean_dec, fgcm_obj[
"ra"][p1a], fgcm_obj[
"dec"][p1a])
747 if rad < hpg.nside_to_resolution(self.config.coarseNside)/2.:
753 reference_filter_names,
758 self.config.coarseNside,
759 hpg.nest_to_ring(self.config.coarseNside, ipnest[p1a[0]]),
760 reference_filter_names,
762 if ref_cat.size == 0:
766 with Matcher(fgcm_obj[
"ra"][p1a], fgcm_obj[
"dec"][p1a])
as matcher:
767 idx, i1, i2, d = matcher.query_radius(
770 self.config.matchRadius/3600.,
778 pixel_cat = Table(data=np.zeros(i1.size, dtype=dtype))
779 pixel_cat[
"fgcm_id"] = fgcm_obj[
"fgcm_id"][p1a[i1]]
780 pixel_cat[
"refMag"][:, :] = ref_cat[
"refMag"][i2, :]
781 pixel_cat[
"refMagErr"][:, :] = ref_cat[
"refMagErr"][i2, :]
783 pixel_cats.append(pixel_cat)
786 "Found %d reference matches in pixel %d (%d of %d).",
793 ref_cat_full = vstack(pixel_cats)
794 ref_cat_full.meta.update({
'FILTERNAMES': reference_filter_names})
799 """Compute delta aperture summary statistics (per visit).
803 visit_cat : `lsst.afw.table.ExposureCatalog`
804 Catalog of per-visit data.
805 star_obs : `astropy.table.Table`
806 Catalog of individual star observations.
808 (ok,) = ((star_obs["delta_mag_aper"] < 99.0)
809 & (star_obs[
"delta_mag_err_aper"] < 99.0)).nonzero()
811 visit_index = np.zeros(len(star_obs[ok]), dtype=np.int32)
812 a, b = esutil.numpy_util.match(visit_cat[
"visit"], star_obs[
"visit"][ok])
815 h, rev = esutil.stat.histogram(visit_index, rev=
True)
817 visit_cat[
"deltaAper"] = -9999.0
818 h_use, = np.where(h >= 3)
820 i1a = rev[rev[index]: rev[index + 1]]
821 visit_cat[
"deltaAper"][index] = np.median(star_obs[
"delta_mag_aper"][ok[i1a]])
apertureOuterInstFluxField
apertureInnerInstFluxField
getSpatialBoundsConnections(self)
__init__(self, *config=None)
runQuantum(self, butlerQC, inputRefs, outputRefs)
_density_downsample(self, fgcm_obj, star_obs)
_mark_reserve_stars(self, fgcm_obj)
run(self, *camera, visit_summary_handle_dict, isolated_star_cat_handle_dict, isolated_star_source_handle_dict, lookup_table_handle=None)
_make_all_star_obs_from_isolated_stars(self, isolated_star_cat_handle_dict, isolated_star_source_handle_dict, visit_cat, camera, calib_flux_aperture_radius=None)
__init__(self, initInputs=None, **kwargs)
_associate_reference_stars(self, lookup_table_handle, visit_cat, fgcm_obj)
_compute_delta_aper_summary_statistics(self, visit_cat, star_obs)
_getReferenceFilterNames(self, visitCat, stdFilterDict, stdLambdaDict)
fgcmMakeVisitCatalog(self, camera, groupedHandles)
apertureOuterInstFluxField
apertureInnerInstFluxField