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)
610 fgcm_obj[
"fgcm_id"][:] = np.arange(len(fgcm_obj)) + 1
612 return vstack(fgcm_objs), vstack(star_obs_cats)
614 def _density_downsample(self, fgcm_obj, star_obs):
615 """Downsample stars according to density.
617 Catalogs are modified in-place.
621 fgcm_obj : `astropy.table.Table`
622 Catalog of per-star ids
and positions.
623 star_obs : `astropy.table.Table`
624 Catalog of individual star observations.
626 if self.config.randomSeed
is not None:
627 np.random.seed(seed=self.config.randomSeed)
629 ipnest = hpg.angle_to_pixel(self.config.densityCutNside, fgcm_obj[
"ra"], fgcm_obj[
"dec"])
633 hist, rev_indices = esutil.stat.histogram(ipnest, rev=
True)
635 obj_use = np.ones(len(fgcm_obj), dtype=bool)
637 (high,) = (hist > self.config.densityCutMaxPerPixel).nonzero()
638 (ok,) = (hist > 0).nonzero()
639 self.log.info(
"There are %d/%d pixels with high stellar density.", high.size, ok.size)
640 for i
in range(high.size):
642 pix_indices = rev_indices[rev_indices[high[i]]: rev_indices[high[i] + 1]]
644 cut = np.random.choice(
646 size=pix_indices.size - self.config.densityCutMaxPerPixel,
651 fgcm_obj = fgcm_obj[obj_use]
653 obs_index = np.zeros(np.sum(fgcm_obj[
"n_obs"]), dtype=np.int32)
655 for i
in range(len(fgcm_obj)):
656 n_obs = fgcm_obj[
"n_obs"][i]
657 obs_index[ctr: ctr + n_obs] = (
658 np.arange(fgcm_obj[
"obs_arr_index"][i], fgcm_obj[
"obs_arr_index"][i] + n_obs)
660 fgcm_obj[
"obs_arr_index"][i] = ctr
663 star_obs = star_obs[obs_index]
665 def _mark_reserve_stars(self, fgcm_obj):
666 """Run the star reservation task to flag reserved stars.
670 fgcm_obj : `astropy.table.Table`
671 Catalog of per-star ids and positions.
673 reserved = self.reserve_selection.run(
675 extra=','.join(self.config.requiredBands),
677 fgcm_obj[
"obj_flag"][reserved] |= objFlagDict[
"RESERVED"]
679 def _associate_reference_stars(self, lookup_table_handle, visit_cat, fgcm_obj):
680 """Associate fgcm isolated stars with reference stars.
684 lookup_table_handle : `lsst.daf.butler.DeferredDatasetHandle`, optional
685 Data reference to fgcm look-up table (used if matching reference stars).
686 visit_cat : `lsst.afw.table.ExposureCatalog`
687 Catalog of per-visit data.
688 fgcm_obj : `astropy.table.Table`
689 Catalog of per-star ids
and positions
693 ref_cat : `astropy.table.Table`
694 Catalog of reference stars matched to fgcm stars.
697 lut_cat = lookup_table_handle.get()
699 std_filter_dict = {filter_name: std_filter
for (filter_name, std_filter)
in
700 zip(lut_cat[0][
"physicalFilters"].split(
","),
701 lut_cat[0][
"stdPhysicalFilters"].split(
","))}
702 std_lambda_dict = {std_filter: std_lambda
for (std_filter, std_lambda)
in
703 zip(lut_cat[0][
"stdPhysicalFilters"].split(
","),
704 lut_cat[0][
"lambdaStdFilter"])}
712 self.log.info(
"Using the following reference filters: %s", (
", ".join(reference_filter_names)))
715 ipnest = hpg.angle_to_pixel(self.config.coarseNside, fgcm_obj[
"ra"], fgcm_obj[
"dec"])
716 hpix, revpix = esutil.stat.histogram(ipnest, rev=
True)
721 dtype = [(
"fgcm_id",
"i4"),
722 (
"refMag",
"f4", (len(reference_filter_names), )),
723 (
"refMagErr",
"f4", (len(reference_filter_names), ))]
725 (gdpix,) = (hpix > 0).nonzero()
726 for ii, gpix
in enumerate(gdpix):
727 p1a = revpix[revpix[gpix]: revpix[gpix + 1]]
730 ra_wrap = fgcm_obj[
"ra"][p1a]
731 if (ra_wrap.min() < 10.0)
and (ra_wrap.max() > 350.0):
732 ra_wrap[ra_wrap > 180.0] -= 360.0
733 mean_ra = np.mean(ra_wrap) % 360.0
735 mean_ra = np.mean(ra_wrap)
736 mean_dec = np.mean(fgcm_obj[
"dec"][p1a])
738 dist = esutil.coords.sphdist(mean_ra, mean_dec, fgcm_obj[
"ra"][p1a], fgcm_obj[
"dec"][p1a])
741 if rad < hpg.nside_to_resolution(self.config.coarseNside)/2.:
743 ref_cat = self.fgcmLoadReferenceCatalog.getFgcmReferenceStarsSkyCircle(
747 reference_filter_names,
751 ref_cat = self.fgcmLoadReferenceCatalog.getFgcmReferenceStarsHealpix(
752 self.config.coarseNside,
753 hpg.nest_to_ring(self.config.coarseNside, ipnest[p1a[0]]),
754 reference_filter_names,
756 if ref_cat.size == 0:
760 with Matcher(fgcm_obj[
"ra"][p1a], fgcm_obj[
"dec"][p1a])
as matcher:
761 idx, i1, i2, d = matcher.query_radius(
764 self.config.matchRadius/3600.,
772 pixel_cat = Table(data=np.zeros(i1.size, dtype=dtype))
773 pixel_cat[
"fgcm_id"] = fgcm_obj[
"fgcm_id"][p1a[i1]]
774 pixel_cat[
"refMag"][:, :] = ref_cat[
"refMag"][i2, :]
775 pixel_cat[
"refMagErr"][:, :] = ref_cat[
"refMagErr"][i2, :]
777 pixel_cats.append(pixel_cat)
780 "Found %d reference matches in pixel %d (%d of %d).",
787 ref_cat_full = vstack(pixel_cats)
788 ref_cat_full.meta.update({
'FILTERNAMES': reference_filter_names})
792 def _compute_delta_aper_summary_statistics(self, visit_cat, star_obs):
793 """Compute delta aperture summary statistics (per visit).
797 visit_cat : `lsst.afw.table.ExposureCatalog`
798 Catalog of per-visit data.
799 star_obs : `astropy.table.Table`
800 Catalog of individual star observations.
802 (ok,) = ((star_obs["delta_mag_aper"] < 99.0)
803 & (star_obs[
"delta_mag_err_aper"] < 99.0)).nonzero()
805 visit_index = np.zeros(len(star_obs[ok]), dtype=np.int32)
806 a, b = esutil.numpy_util.match(visit_cat[
"visit"], star_obs[
"visit"][ok])
809 h, rev = esutil.stat.histogram(visit_index, rev=
True)
811 visit_cat[
"deltaAper"] = -9999.0
812 h_use, = np.where(h >= 3)
814 i1a = rev[rev[index]: rev[index + 1]]
815 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