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.
34from smatch.matcher import Matcher
35from astropy.table import Table, vstack
37from fgcm.fgcmUtilities import objFlagDict
39import lsst.pex.config as pexConfig
40import lsst.pipe.base as pipeBase
41from lsst.pipe.base import connectionTypes
42from lsst.meas.algorithms import ReferenceObjectLoader, LoadReferenceObjectsConfig
43from lsst.pipe.tasks.reserveIsolatedStars import ReserveIsolatedStarsTask
45from .fgcmBuildStarsBase import FgcmBuildStarsConfigBase, FgcmBuildStarsBaseTask
46from .utilities import computeApproxPixelAreaFields, computeApertureRadiusFromName
47from .utilities import lookupStaticCalibrations
49__all__ = ["FgcmBuildFromIsolatedStarsConfig", "FgcmBuildFromIsolatedStarsTask"]
52class FgcmBuildFromIsolatedStarsConnections(pipeBase.PipelineTaskConnections,
53 dimensions=("instrument",),
55 camera = connectionTypes.PrerequisiteInput(
56 doc=
"Camera instrument",
58 storageClass=
"Camera",
59 dimensions=(
"instrument",),
60 lookupFunction=lookupStaticCalibrations,
63 fgcm_lookup_table = connectionTypes.PrerequisiteInput(
64 doc=(
"Atmosphere + instrument look-up-table for FGCM throughput and "
65 "chromatic corrections."),
66 name=
"fgcmLookUpTable",
67 storageClass=
"Catalog",
68 dimensions=(
"instrument",),
71 ref_cat = connectionTypes.PrerequisiteInput(
72 doc=
"Reference catalog to use for photometric calibration.",
74 storageClass=
"SimpleCatalog",
75 dimensions=(
"skypix",),
79 isolated_star_cats = pipeBase.connectionTypes.Input(
80 doc=(
"Catalog of isolated stars with average positions, number of associated "
81 "sources, and indexes to the isolated_star_sources catalogs."),
82 name=
"isolated_star_cat",
83 storageClass=
"ArrowAstropy",
84 dimensions=(
"instrument",
"tract",
"skymap"),
88 isolated_star_sources = pipeBase.connectionTypes.Input(
89 doc=(
"Catalog of isolated star sources with sourceIds, and indexes to the "
90 "isolated_star_cats catalogs."),
91 name=
"isolated_star_sources",
92 storageClass=
"ArrowAstropy",
93 dimensions=(
"instrument",
"tract",
"skymap"),
97 visit_summaries = connectionTypes.Input(
98 doc=(
"Per-visit consolidated exposure metadata. These catalogs use "
99 "detector id for the id and must be sorted for fast lookups of a "
102 storageClass=
"ExposureCatalog",
103 dimensions=(
"instrument",
"visit"),
107 fgcm_visit_catalog = connectionTypes.Output(
108 doc=
"Catalog of visit information for fgcm.",
109 name=
"fgcmVisitCatalog",
110 storageClass=
"Catalog",
111 dimensions=(
"instrument",),
113 fgcm_star_observations = connectionTypes.Output(
114 doc=
"Catalog of star observations for fgcm.",
115 name=
"fgcm_star_observations",
116 storageClass=
"ArrowAstropy",
117 dimensions=(
"instrument",),
119 fgcm_star_ids = connectionTypes.Output(
120 doc=
"Catalog of fgcm calibration star IDs.",
121 name=
"fgcm_star_ids",
122 storageClass=
"ArrowAstropy",
123 dimensions=(
"instrument",),
125 fgcm_reference_stars = connectionTypes.Output(
126 doc=
"Catalog of fgcm-matched reference stars.",
127 name=
"fgcm_reference_stars",
128 storageClass=
"ArrowAstropy",
129 dimensions=(
"instrument",),
135 if not config.doReferenceMatches:
136 self.prerequisiteInputs.remove(
"ref_cat")
137 self.prerequisiteInputs.remove(
"fgcm_lookup_table")
138 self.outputs.remove(
"fgcm_reference_stars")
142 pipelineConnections=FgcmBuildFromIsolatedStarsConnections):
143 """Config for FgcmBuildFromIsolatedStarsTask."""
144 referenceCCD = pexConfig.Field(
145 doc=
"Reference detector for checking PSF and background.",
149 reserve_selection = pexConfig.ConfigurableField(
150 target=ReserveIsolatedStarsTask,
151 doc=
"Task to select reserved stars.",
167 source_selector.setDefaults()
169 source_selector.doFlags =
False
170 source_selector.doSignalToNoise =
True
171 source_selector.doUnresolved =
False
172 source_selector.doIsolated =
False
173 source_selector.doRequireFiniteRaDec =
False
175 source_selector.flags.bad = []
177 source_selector.signalToNoise.minimum = 11.0
178 source_selector.signalToNoise.maximum = 1000.0
184 """Build star catalog for FGCM global calibration, using the isolated star catalogs.
186 ConfigClass = FgcmBuildFromIsolatedStarsConfig
187 _DefaultName = "fgcmBuildFromIsolatedStars"
189 canMultiprocess =
False
193 self.makeSubtask(
'reserve_selection')
196 input_ref_dict = butlerQC.get(inputRefs)
198 isolated_star_cat_handles = input_ref_dict[
"isolated_star_cats"]
199 isolated_star_source_handles = input_ref_dict[
"isolated_star_sources"]
201 isolated_star_cat_handle_dict = {
202 handle.dataId[
"tract"]: handle
for handle
in isolated_star_cat_handles
204 isolated_star_source_handle_dict = {
205 handle.dataId[
"tract"]: handle
for handle
in isolated_star_source_handles
208 if len(isolated_star_cat_handle_dict) != len(isolated_star_source_handle_dict):
209 raise RuntimeError(
"isolated_star_cats and isolate_star_sources must have same length.")
211 for tract
in isolated_star_cat_handle_dict:
212 if tract
not in isolated_star_source_handle_dict:
213 raise RuntimeError(f
"tract {tract} in isolated_star_cats but not isolated_star_sources")
215 if self.config.doReferenceMatches:
216 lookup_table_handle = input_ref_dict[
"fgcm_lookup_table"]
219 ref_config = LoadReferenceObjectsConfig()
220 ref_config.filterMap = self.config.fgcmLoadReferenceCatalog.filterMap
221 ref_obj_loader = ReferenceObjectLoader(dataIds=[ref.datasetRef.dataId
222 for ref
in inputRefs.ref_cat],
223 refCats=butlerQC.get(inputRefs.ref_cat),
224 name=self.config.connections.ref_cat,
227 self.makeSubtask(
'fgcmLoadReferenceCatalog',
228 refObjLoader=ref_obj_loader,
229 refCatName=self.config.connections.ref_cat)
231 lookup_table_handle =
None
237 visit_summary_handle_dict = {handle.dataId[
'visit']: [handle,
None]
for
238 handle
in input_ref_dict[
'visit_summaries']}
240 camera = input_ref_dict[
"camera"]
244 visit_summary_handle_dict=visit_summary_handle_dict,
245 isolated_star_cat_handle_dict=isolated_star_cat_handle_dict,
246 isolated_star_source_handle_dict=isolated_star_source_handle_dict,
247 lookup_table_handle=lookup_table_handle,
250 butlerQC.put(struct.fgcm_visit_catalog, outputRefs.fgcm_visit_catalog)
251 butlerQC.put(struct.fgcm_star_observations, outputRefs.fgcm_star_observations)
252 butlerQC.put(struct.fgcm_star_ids, outputRefs.fgcm_star_ids)
253 if self.config.doReferenceMatches:
254 butlerQC.put(struct.fgcm_reference_stars, outputRefs.fgcm_reference_stars)
256 def run(self, *, camera, visit_summary_handle_dict, isolated_star_cat_handle_dict,
257 isolated_star_source_handle_dict, lookup_table_handle=None):
258 """Run the fgcmBuildFromIsolatedStarsTask.
262 camera : `lsst.afw.cameraGeom.Camera`
264 visit_summary_handle_dict : `dict` [`int`, [`lsst.daf.butler.DeferredDatasetHandle`]]
265 Visit summary dataset handles, with the visit
as key.
266 isolated_star_cat_handle_dict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`]
267 Isolated star catalog dataset handles,
with the tract
as key.
268 isolated_star_source_handle_dict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`]
269 Isolated star source dataset handles,
with the tract
as key.
270 lookup_table_handle : `lsst.daf.butler.DeferredDatasetHandle`, optional
271 Data reference to fgcm look-up table (used
if matching reference stars).
275 struct : `lsst.pipe.base.struct`
276 Catalogs
for persistence,
with attributes:
278 ``fgcm_visit_catalog``
279 Catalog of per-visit data (`lsst.afw.table.ExposureCatalog`).
280 ``fgcm_star_observations``
281 Catalog of individual star observations (`astropy.table.Table`).
283 Catalog of per-star ids
and positions (`astropy.table.Table`).
284 ``fgcm_reference_stars``
285 Catalog of reference stars matched to fgcm stars (`astropy.table.Table`).
289 calib_flux_aperture_radius =
None
290 if self.config.doSubtractLocalBackground:
292 calib_flux_aperture_radius = computeApertureRadiusFromName(self.config.instFluxField)
293 except RuntimeError
as e:
294 raise RuntimeError(
"Could not determine aperture radius from %s. "
295 "Cannot use doSubtractLocalBackground." %
296 (self.config.instFluxField))
from e
299 if self.config.doReferenceMatches:
300 if lookup_table_handle
is None:
301 raise RuntimeError(
"Must supply lookup_table_handle if config.doReferenceMatches is True.")
307 isolated_star_cat_handle_dict,
308 isolated_star_source_handle_dict,
311 calib_flux_aperture_radius=calib_flux_aperture_radius,
326 if self.config.doReferenceMatches:
331 return pipeBase.Struct(
332 fgcm_visit_catalog=visit_cat,
333 fgcm_star_observations=star_obs,
334 fgcm_star_ids=fgcm_obj,
335 fgcm_reference_stars=fgcm_ref,
338 def _make_all_star_obs_from_isolated_stars(
340 isolated_star_cat_handle_dict,
341 isolated_star_source_handle_dict,
344 calib_flux_aperture_radius=None,
346 """Make all star observations from isolated star catalogs.
350 isolated_star_cat_handle_dict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`]
351 Isolated star catalog dataset handles, with the tract
as key.
352 isolated_star_source_handle_dict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`]
353 Isolated star source dataset handles,
with the tract
as key.
354 visit_cat : `lsst.afw.table.ExposureCatalog`
355 Catalog of per-visit data.
356 camera : `lsst.afw.cameraGeom.Camera`
358 calib_flux_aperture_radius : `float`, optional
359 Radius
for the calibration flux aperture.
363 fgcm_obj : `astropy.table.Table`
364 Catalog of ids
and positions
for each star.
365 star_obs : `astropy.table.Table`
366 Catalog of individual star observations.
379 self.config.instFluxField,
380 self.config.instFluxField +
"Err",
381 self.config.apertureInnerInstFluxField,
382 self.config.apertureInnerInstFluxField +
"Err",
383 self.config.apertureOuterInstFluxField,
384 self.config.apertureOuterInstFluxField +
"Err",
387 if self.config.doSubtractLocalBackground:
388 source_columns.append(self.config.localBackgroundFluxField)
389 local_background_flag_name = self.config.localBackgroundFluxField[0: -len(
'instFlux')] +
'flag'
390 source_columns.append(local_background_flag_name)
392 if self.sourceSelector.config.doFlags:
393 source_columns.extend(self.sourceSelector.config.flags.bad)
395 local_background_area = np.pi*calib_flux_aperture_radius**2.
399 approx_pixel_area_fields = computeApproxPixelAreaFields(camera)
402 detector_mapping = {}
403 for detector_index, detector
in enumerate(camera):
404 detector_mapping[detector.getId()] = detector_index
414 (
"inst_mag_err",
"f4"),
416 (
"delta_mag_bkg",
"f4"),
417 (
"delta_mag_aper",
"f4"),
418 (
"delta_mag_err_aper",
"f4"),
423 (
"isolated_star_id",
"i8"),
426 (
"obs_arr_index",
"i4"),
433 merge_source_counter = 0
437 visit_cat_table = visit_cat.asAstropy()
439 for tract
in sorted(isolated_star_cat_handle_dict):
440 stars = isolated_star_cat_handle_dict[tract].get()
441 sources = isolated_star_source_handle_dict[tract].get(parameters={
"columns": source_columns})
444 good_sources = self.sourceSelector.selectSources(sources).selected
445 if self.config.doSubtractLocalBackground:
446 good_sources &= (~sources[local_background_flag_name])
447 local_background = local_background_area*sources[self.config.localBackgroundFluxField]
448 good_sources &= ((sources[self.config.instFluxField] - local_background) > 0)
450 if good_sources.sum() == 0:
451 self.log.info(
"No good sources found in tract %d", tract)
459 if len(self.config.requiredBands) > 0:
460 loop_bands = self.config.requiredBands
462 loop_bands = np.unique(sources[
"band"])
464 n_req = np.zeros((len(loop_bands), len(stars)), dtype=np.int32)
465 for i, band
in enumerate(loop_bands):
466 (band_use,) = (sources[good_sources][
"band"] == band).nonzero()
469 (i, sources[good_sources][
"obj_index"][band_use]),
473 if len(self.config.requiredBands) > 0:
476 (good_stars,) = (n_req.min(axis=0) >= self.config.minPerBand).nonzero()
480 (good_stars,) = (n_req.max(axis=0) >= self.config.minPerBand).nonzero()
484 obj_index = sources[
"obj_index"][good_sources]
485 a, b = esutil.numpy_util.match(good_stars, obj_index)
488 _, index_new = np.unique(a, return_index=
True)
489 stars[
"source_cat_index"][good_stars] = index_new
490 sources = sources[good_sources][b]
491 sources[
"obj_index"][:] = a
492 stars = stars[good_stars]
494 nsource = np.zeros(len(stars), dtype=np.int32)
497 sources[
"obj_index"],
500 stars[
"nsource"][:] = nsource
513 star_obs = Table(data=np.zeros(len(sources), dtype=star_obs_dtype))
514 star_obs[
"ra"] = sources[
"ra"]
515 star_obs[
"dec"] = sources[
"decl"]
516 star_obs[
"x"] = sources[
"x"]
517 star_obs[
"y"] = sources[
"y"]
518 star_obs[
"visit"] = sources[
"visit"]
519 star_obs[
"detector"] = sources[
"detector"]
521 visit_match, obs_match = esutil.numpy_util.match(visit_cat_table[
"visit"], sources[
"visit"])
523 exp_time = np.zeros(len(star_obs))
524 exp_time[obs_match] = visit_cat_table[
"exptime"][visit_match]
526 with np.warnings.catch_warnings():
528 np.warnings.simplefilter(
"ignore")
530 inst_mag_inner = -2.5*np.log10(sources[self.config.apertureInnerInstFluxField])
531 inst_mag_err_inner = k*(sources[self.config.apertureInnerInstFluxField +
"Err"]
532 / sources[self.config.apertureInnerInstFluxField])
533 inst_mag_outer = -2.5*np.log10(sources[self.config.apertureOuterInstFluxField])
534 inst_mag_err_outer = k*(sources[self.config.apertureOuterInstFluxField +
"Err"]
535 / sources[self.config.apertureOuterInstFluxField])
536 star_obs[
"delta_mag_aper"] = inst_mag_inner - inst_mag_outer
537 star_obs[
"delta_mag_err_aper"] = np.sqrt(inst_mag_err_inner**2. + inst_mag_err_outer**2.)
539 bad = ~np.isfinite(star_obs[
"delta_mag_aper"])
540 star_obs[
"delta_mag_aper"][bad] = 99.0
541 star_obs[
"delta_mag_err_aper"][bad] = 99.0
543 if self.config.doSubtractLocalBackground:
557 local_background = local_background_area*sources[self.config.localBackgroundFluxField]
558 star_obs[
"delta_mag_bkg"] = (-2.5*np.log10(sources[self.config.instFluxField]
559 - local_background) -
560 -2.5*np.log10(sources[self.config.instFluxField]))
563 for detector
in camera:
564 detector_id = detector.getId()
566 (use,) = (star_obs[
"detector"][obs_match] == detector_id).nonzero()
574 jac = approx_pixel_area_fields[detector_id].evaluate(
575 star_obs[
"x"][obs_match][use],
576 star_obs[
"y"][obs_match][use],
578 star_obs[
"jacobian"][obs_match[use]] = jac
579 scaled_inst_flux = (sources[self.config.instFluxField][obs_match[use]]
580 * visit_cat_table[
"scaling"][visit_match[use],
581 detector_mapping[detector_id]])
582 star_obs[
"inst_mag"][obs_match[use]] = (-2.5 * np.log10(scaled_inst_flux
586 star_obs[
"inst_mag_err"] = k*(sources[self.config.instFluxField +
"Err"]
587 / sources[self.config.instFluxField])
590 if self.config.doApplyWcsJacobian:
591 star_obs[
"inst_mag"] -= 2.5*np.log10(star_obs[
"jacobian"])
594 fgcm_obj = Table(data=np.zeros(len(stars), dtype=fgcm_obj_dtype))
595 fgcm_obj[
"isolated_star_id"] = stars[
"isolated_star_id"]
596 fgcm_obj[
"ra"] = stars[
"ra"]
597 fgcm_obj[
"dec"] = stars[
"decl"]
598 fgcm_obj[
"obs_arr_index"] = stars[
"source_cat_index"]
599 fgcm_obj[
"n_obs"] = stars[
"nsource"]
602 fgcm_obj[
"obs_arr_index"] += merge_source_counter
604 fgcm_objs.append(fgcm_obj)
605 star_obs_cats.append(star_obs)
607 merge_source_counter += len(star_obs)
609 fgcm_obj = vstack(fgcm_objs)
612 fgcm_obj[
"fgcm_id"][:] = np.arange(len(fgcm_obj)) + 1
614 return fgcm_obj, vstack(star_obs_cats)
616 def _density_downsample(self, fgcm_obj, star_obs):
617 """Downsample stars according to density.
619 Catalogs are modified in-place.
623 fgcm_obj : `astropy.table.Table`
624 Catalog of per-star ids
and positions.
625 star_obs : `astropy.table.Table`
626 Catalog of individual star observations.
628 if self.config.randomSeed
is not None:
629 np.random.seed(seed=self.config.randomSeed)
631 ipnest = hpg.angle_to_pixel(self.config.densityCutNside, fgcm_obj[
"ra"], fgcm_obj[
"dec"])
635 hist, rev_indices = esutil.stat.histogram(ipnest, rev=
True)
637 obj_use = np.ones(len(fgcm_obj), dtype=bool)
639 (high,) = (hist > self.config.densityCutMaxPerPixel).nonzero()
640 (ok,) = (hist > 0).nonzero()
641 self.log.info(
"There are %d/%d pixels with high stellar density.", high.size, ok.size)
642 for i
in range(high.size):
644 pix_indices = rev_indices[rev_indices[high[i]]: rev_indices[high[i] + 1]]
646 cut = np.random.choice(
648 size=pix_indices.size - self.config.densityCutMaxPerPixel,
653 fgcm_obj = fgcm_obj[obj_use]
655 obs_index = np.zeros(np.sum(fgcm_obj[
"n_obs"]), dtype=np.int32)
657 for i
in range(len(fgcm_obj)):
658 n_obs = fgcm_obj[
"n_obs"][i]
659 obs_index[ctr: ctr + n_obs] = (
660 np.arange(fgcm_obj[
"obs_arr_index"][i], fgcm_obj[
"obs_arr_index"][i] + n_obs)
662 fgcm_obj[
"obs_arr_index"][i] = ctr
665 star_obs = star_obs[obs_index]
667 def _mark_reserve_stars(self, fgcm_obj):
668 """Run the star reservation task to flag reserved stars.
672 fgcm_obj : `astropy.table.Table`
673 Catalog of per-star ids and positions.
675 reserved = self.reserve_selection.run(
677 extra=','.join(self.config.requiredBands),
679 fgcm_obj[
"obj_flag"][reserved] |= objFlagDict[
"RESERVED"]
681 def _associate_reference_stars(self, lookup_table_handle, visit_cat, fgcm_obj):
682 """Associate fgcm isolated stars with reference stars.
686 lookup_table_handle : `lsst.daf.butler.DeferredDatasetHandle`, optional
687 Data reference to fgcm look-up table (used if matching reference stars).
688 visit_cat : `lsst.afw.table.ExposureCatalog`
689 Catalog of per-visit data.
690 fgcm_obj : `astropy.table.Table`
691 Catalog of per-star ids
and positions
695 ref_cat : `astropy.table.Table`
696 Catalog of reference stars matched to fgcm stars.
699 lut_cat = lookup_table_handle.get()
701 std_filter_dict = {filter_name: std_filter
for (filter_name, std_filter)
in
702 zip(lut_cat[0][
"physicalFilters"].split(
","),
703 lut_cat[0][
"stdPhysicalFilters"].split(
","))}
704 std_lambda_dict = {std_filter: std_lambda
for (std_filter, std_lambda)
in
705 zip(lut_cat[0][
"stdPhysicalFilters"].split(
","),
706 lut_cat[0][
"lambdaStdFilter"])}
714 self.log.info(
"Using the following reference filters: %s", (
", ".join(reference_filter_names)))
717 ipnest = hpg.angle_to_pixel(self.config.coarseNside, fgcm_obj[
"ra"], fgcm_obj[
"dec"])
718 hpix, revpix = esutil.stat.histogram(ipnest, rev=
True)
723 dtype = [(
"fgcm_id",
"i4"),
724 (
"refMag",
"f4", (len(reference_filter_names), )),
725 (
"refMagErr",
"f4", (len(reference_filter_names), ))]
727 (gdpix,) = (hpix > 0).nonzero()
728 for ii, gpix
in enumerate(gdpix):
729 p1a = revpix[revpix[gpix]: revpix[gpix + 1]]
732 ra_wrap = fgcm_obj[
"ra"][p1a]
733 if (ra_wrap.min() < 10.0)
and (ra_wrap.max() > 350.0):
734 ra_wrap[ra_wrap > 180.0] -= 360.0
735 mean_ra = np.mean(ra_wrap) % 360.0
737 mean_ra = np.mean(ra_wrap)
738 mean_dec = np.mean(fgcm_obj[
"dec"][p1a])
740 dist = esutil.coords.sphdist(mean_ra, mean_dec, fgcm_obj[
"ra"][p1a], fgcm_obj[
"dec"][p1a])
743 if rad < hpg.nside_to_resolution(self.config.coarseNside)/2.:
745 ref_cat = self.fgcmLoadReferenceCatalog.getFgcmReferenceStarsSkyCircle(
749 reference_filter_names,
753 ref_cat = self.fgcmLoadReferenceCatalog.getFgcmReferenceStarsHealpix(
754 self.config.coarseNside,
755 hpg.nest_to_ring(self.config.coarseNside, ipnest[p1a[0]]),
756 reference_filter_names,
758 if ref_cat.size == 0:
762 with Matcher(fgcm_obj[
"ra"][p1a], fgcm_obj[
"dec"][p1a])
as matcher:
763 idx, i1, i2, d = matcher.query_radius(
766 self.config.matchRadius/3600.,
774 pixel_cat = Table(data=np.zeros(i1.size, dtype=dtype))
775 pixel_cat[
"fgcm_id"] = fgcm_obj[
"fgcm_id"][p1a[i1]]
776 pixel_cat[
"refMag"][:, :] = ref_cat[
"refMag"][i2, :]
777 pixel_cat[
"refMagErr"][:, :] = ref_cat[
"refMagErr"][i2, :]
779 pixel_cats.append(pixel_cat)
782 "Found %d reference matches in pixel %d (%d of %d).",
789 ref_cat_full = vstack(pixel_cats)
790 ref_cat_full.meta.update({
'FILTERNAMES': reference_filter_names})
794 def _compute_delta_aper_summary_statistics(self, visit_cat, star_obs):
795 """Compute delta aperture summary statistics (per visit).
799 visit_cat : `lsst.afw.table.ExposureCatalog`
800 Catalog of per-visit data.
801 star_obs : `astropy.table.Table`
802 Catalog of individual star observations.
804 (ok,) = ((star_obs["delta_mag_aper"] < 99.0)
805 & (star_obs[
"delta_mag_err_aper"] < 99.0)).nonzero()
807 visit_index = np.zeros(len(star_obs[ok]), dtype=np.int32)
808 a, b = esutil.numpy_util.match(visit_cat[
"visit"], star_obs[
"visit"][ok])
811 h, rev = esutil.stat.histogram(visit_index, rev=
True)
813 visit_cat[
"deltaAper"] = -9999.0
814 h_use, = np.where(h >= 3)
816 i1a = rev[rev[index]: rev[index + 1]]
817 visit_cat[
"deltaAper"][index] = np.median(star_obs[
"delta_mag_aper"][ok[i1a]])
apertureOuterInstFluxField
apertureInnerInstFluxField
def __init__(self, *config=None)
def _associate_reference_stars(self, lookup_table_handle, visit_cat, fgcm_obj)
def _density_downsample(self, fgcm_obj, star_obs)
def runQuantum(self, butlerQC, inputRefs, outputRefs)
def run(self, *camera, visit_summary_handle_dict, isolated_star_cat_handle_dict, isolated_star_source_handle_dict, lookup_table_handle=None)
def _compute_delta_aper_summary_statistics(self, visit_cat, star_obs)
def _mark_reserve_stars(self, fgcm_obj)
def _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)
def __init__(self, initInputs=None, **kwargs)
def _getReferenceFilterNames(self, visitCat, stdFilterDict, stdLambdaDict)
def fgcmMakeVisitCatalog(self, camera, groupedHandles)
apertureOuterInstFluxField
apertureInnerInstFluxField