From 4d03c91bc82dbfdd56878d25235ab4a034f01a73 Mon Sep 17 00:00:00 2001 From: Robert Lupton the Good Date: Mon, 17 Jun 2024 16:29:21 -1000 Subject: [PATCH 1/2] Treat all NaNs as equivalent in magnitude arrays --- python/pfs/drp/stella/coaddSpectra.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/python/pfs/drp/stella/coaddSpectra.py b/python/pfs/drp/stella/coaddSpectra.py index bad9a2cc6..fcd9ce475 100644 --- a/python/pfs/drp/stella/coaddSpectra.py +++ b/python/pfs/drp/stella/coaddSpectra.py @@ -33,6 +33,21 @@ __all__ = ("CoaddSpectraConfig", "CoaddSpectraTask") +class SetWithNaN(set): + """A set which includes at most one NaN, despite the fact that NaN != NaN""" + def __init__(self, iterable): + """Construct a set from iterable with at most one NaN""" + sawNaN = False + + for x in iterable: + if np.isnan(x): + if not sawNaN: + self.add(x) + sawNaN = True + else: + self.add(x) + + class CoaddSpectraConnections( PipelineTaskConnections, dimensions=("instrument", "skymap", "tract", "patch"), @@ -289,7 +304,7 @@ def getTarget(self, target: Target, pfsConfigList: List[PfsConfig]) -> Target: for ff, flux in zip(pfsConfig.filterNames[0], pfsConfig.fiberFlux[0]): fiberFlux[ff].append(flux) for ff in fiberFlux: - flux = set(fiberFlux[ff]) + flux = SetWithNaN(fiberFlux[ff]) if len(flux) > 1: self.log.warn("Multiple %s flux for target %s (%s); using average" % (ff, target, flux)) flux = np.average(np.array(fiberFlux[ff])) From e6252cd1e01a39ca23eea46fce2e0a4eb3a8f9cf Mon Sep 17 00:00:00 2001 From: Robert Lupton the Good Date: Tue, 18 Jun 2024 09:42:08 -1000 Subject: [PATCH 2/2] Redo SetWithNaN to avoid methods which circumvent protections --- python/pfs/drp/stella/coaddSpectra.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/python/pfs/drp/stella/coaddSpectra.py b/python/pfs/drp/stella/coaddSpectra.py index fcd9ce475..ac6ded30a 100644 --- a/python/pfs/drp/stella/coaddSpectra.py +++ b/python/pfs/drp/stella/coaddSpectra.py @@ -33,20 +33,37 @@ __all__ = ("CoaddSpectraConfig", "CoaddSpectraTask") -class SetWithNaN(set): - """A set which includes at most one NaN, despite the fact that NaN != NaN""" +class SetWithNaN: + """A subset of set which includes at most one NaN, despite the fact that NaN != NaN""" + def __init__(self, iterable): """Construct a set from iterable with at most one NaN""" + self.__set = set() sawNaN = False for x in iterable: if np.isnan(x): if not sawNaN: - self.add(x) + self.__set.add(x) sawNaN = True else: self.add(x) + def add(self, val): + if np.isnan(val) and np.isnan(list(self)).any(): + return + + self.__set.add(val) + + def __len__(self): + return self.__set.__len__() + + def __repr__(self): + return self.__set.__repr__() + + def pop(self): + return self.__set.pop() + class CoaddSpectraConnections( PipelineTaskConnections,