Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-28459: Standardize LSSTCam and LATISS filter band derivations #287

Merged
merged 7 commits into from
Feb 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
144 changes: 72 additions & 72 deletions python/lsst/obs/lsst/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@
def addFilter(filter_dict, band, physical_filter, lambdaEff=0.0):
"""Define a filter in filter_dict, to be converted to a Filter later"""

# index by band but keep distinct physical filters by band
# since there can be many physical filters for a single band
if band not in filter_dict:
filter_dict[band] = dict(physical_filter=physical_filter,
lambdaEff=lambdaEff, alias=[])
else:
assert filter_dict[band]["lambdaEff"] == lambdaEff
filter_dict[band] = {}

filter_dict[band]["alias"].append(physical_filter)
filter_dict[band][physical_filter] = dict(physical_filter=physical_filter,
band=band, lambdaEff=lambdaEff, alias=[],
)


# The LSST Filters from L. Jones 05/14/2020 - "Edges" = 5% of peak throughput
Expand Down Expand Up @@ -86,80 +87,67 @@ def addFilter(filter_dict, band, physical_filter, lambdaEff=0.0):
#
# The band names are not yet defined, so I'm going to invent them

# Map the BOT filters to corresponding band explicitly
BOT_filter_map = {
"empty": "white",
"SDSSu": "u",
"SDSSg": "g",
"SDSSr": "r",
"SDSSi": "i",
"SDSSz": "z",
"SDSSY": "y",
"480nm": "g",
"650nm": "r",
"750nm": "i",
"870nm": "z",
"950nm": "y",
"970nm": "y",
"grid": "grid",
"spot": "spot",
}

BOTFilters_dict = {}
for physical_filter in [
"empty",
"SDSSu",
"SDSSg",
"SDSSr",
"SDSSi",
"SDSSz",
"SDSSY",
"480nm",
"650nm",
"750nm",
"870nm",
"950nm",
"970nm",
"grid",
"spot",
"empty3",
"empty4",
"empty5",
"empty6",
]:
mat = re.search(r"^SDSS(.)$", physical_filter)
if mat:
band = mat.group(1).lower()

lsstCamFilter = [f for f in LsstCamFiltersBaseline if f.band == band][0]
lambdaEff = lsstCamFilter.lambdaEff
else:
if re.search(r"^empty[3-6]$", physical_filter):
band = "white"
else:
band = physical_filter
lambdaEff = 0.0
for physical_filter, band in BOT_filter_map.items():
lambdaEff = 0.0
lsstCamFilterMatches = [f for f in LsstCamFiltersBaseline if f.band == band]
if lsstCamFilterMatches:
lambdaEff = lsstCamFilterMatches[0].lambdaEff

if mat := re.match(r"(\d+)nm$", physical_filter):
lambdaEff = float(mat.group(1))

if physical_filter == "empty":
pass # already in LsstCamFiltersBaseline
pass # Already defined above
else:
addFilter(BOTFilters_dict, band, physical_filter, lambdaEff=lambdaEff)

ndFilters = ["empty", "ND_OD0.1", "ND_OD0.3", "ND_OD0.5", "ND_OD0.7", "ND_OD1.0", "ND_OD2.0"]
# Empty ND is removed by metadata translator so is not needed here
ndFilters = ["ND_OD0.1", "ND_OD0.3", "ND_OD0.5", "ND_OD0.7", "ND_OD1.0", "ND_OD2.0"]
# We found these additional filters in BOT data files:
ndFilters += ['ND_OD0.01', 'ND_OD0.05', 'ND_OD0.4', 'ND_OD3.0', 'ND_OD4.0']

for nd in ndFilters:
pf = f"{physical_filter}{FILTER_DELIMITER}{nd}" # fully qualified physical filter
# fully qualified physical filter
phys_plus_nd = f"{physical_filter}{FILTER_DELIMITER}{nd}"

# When one of the filters is empty we can just use the real filter
# (e.g. "u" not "u~empty"); but we always need at least one "empty"
#
# Don't use . in band names, it's just asking for trouble
# if they ever end up in filenames
if nd == "empty":
if band == "white":
af = "white"
else:
af = f"{band}"
elif band == "white":
pf = nd
af = f"{nd.replace('.', '_')}"
else:
af = f"{band}{FILTER_DELIMITER}{nd.replace('.', '_')}"

addFilter(BOTFilters_dict, band=af, physical_filter=pf, lambdaEff=lambdaEff)
if band == "white":
# Use the ND on its own
phys_plus_nd = nd

# Use a generic ND modifier for the band
ndband = f"{band}{FILTER_DELIMITER}nd"

addFilter(BOTFilters_dict, band=ndband, physical_filter=phys_plus_nd, lambdaEff=lambdaEff)

BOTFilters = [
FilterDefinition(band="unknown", physical_filter="unknown", lambdaEff=0.0),
]
for band, filt in BOTFilters_dict.items():
BOTFilters.append(FilterDefinition(band=band,
physical_filter=filt["physical_filter"],
lambdaEff=filt["lambdaEff"],
alias=filt["alias"]))
for band, physical_filters in BOTFilters_dict.items():
for physical_filter, filter_defn in physical_filters.items():
BOTFilters.append(FilterDefinition(**filter_defn))

#
# The filters that we might see in the real LSSTCam (including in SLAC)
#
Expand Down Expand Up @@ -202,9 +190,11 @@ def addFilter(filter_dict, band, physical_filter, lambdaEff=0.0):
# filters for each combination of filter+grating.
_latiss_filters = (
FilterDefinition(physical_filter="empty",
band="white",
lambdaEff=0.0,
alias={"no_filter", "open"}),
FilterDefinition(physical_filter="blank_bk7_wg05",
band="white",
lambdaEff=0.0),
FilterDefinition(physical_filter="KPNO_1111_436nm",
band="g",
Expand All @@ -216,39 +206,51 @@ def addFilter(filter_dict, band, physical_filter, lambdaEff=0.0):
band="z",
lambdaEff=828.0, lambdaMin=738.5, lambdaMax=917.5),
FilterDefinition(physical_filter="diffuser",
lambdaEff=0.0),
FilterDefinition(physical_filter="empty",
band="diffuser",
lambdaEff=0.0),
FilterDefinition(physical_filter="unknown",
band="unknown",
lambdaEff=0.0),
FilterDefinition(physical_filter="BG40",
# band="g", # afw only allows one g filter
band="g",
afw_name="bg",
lambdaEff=472.0, lambdaMin=334.5, lambdaMax=609.5),
FilterDefinition(physical_filter="quadnotch1",
lambdaEff=0.0),
lambdaEff=0.0,
band="notch"),
FilterDefinition(physical_filter="RG610",
lambdaEff=0.0),
lambdaEff=0.0,
band="r",
afw_name="rg"),
)

# Form a new set of filter definitions from all the explicit filters
_latiss_gratings = ("ronchi90lpmm", "ronchi170lpmm", "empty", "none", "unknown")
_latiss_gratings = ("ronchi90lpmm", "ronchi170lpmm", "empty", "unknown")

# Include the filters without the grating in case someone wants
# to retrieve a filter by an actual filter name
_latiss_filter_and_grating = [f for f in _latiss_filters]

for filter in _latiss_filters:
for grating in _latiss_gratings:
# The diffuser "filter" was never used with gratings
# so skip it
if filter.physical_filter == "diffuser":
continue
Comment on lines +236 to +239
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is likely fine, I just worry that just because that wasn't happened to date, that doesn't mean it never will in future. But I think this is probably fine for now, give we're really trying to keep the numbers down.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If new diffuser data turns up we can sort it out at the time.


# FilterDefinition is a frozen dataclass
new_name = FILTER_DELIMITER.join([filter.physical_filter, grating])

# Also need to update aliases
new_aliases = {FILTER_DELIMITER.join([a, grating]) for a in filter.alias}

# For gratings set the band to the band of the filter
combo = FilterDefinition(physical_filter=new_name,
band=filter.band,
lambdaEff=filter.lambdaEff,
lambdaMin=filter.lambdaMin,
lambdaMax=filter.lambdaMax,
afw_name=filter.afw_name,
alias=new_aliases)
_latiss_filter_and_grating.append(combo)

Expand Down Expand Up @@ -308,11 +310,9 @@ def addFilter(filter_dict, band, physical_filter, lambdaEff=0.0):
FilterDefinition(band="white", physical_filter="empty", lambdaEff=0.0),
FilterDefinition(band="unknown", physical_filter="unknown", lambdaEff=0.0),
]
for band, filt in ComCamFilters_dict.items():
ComCamFilters.append(FilterDefinition(band=band,
physical_filter=filt["physical_filter"],
lambdaEff=filt["lambdaEff"],
alias=filt["alias"]))
for band, physical_filters in ComCamFilters_dict.items():
for physical_filter, filter_defn in physical_filters.items():
ComCamFilters.append(FilterDefinition(**filter_defn))

COMCAM_FILTER_DEFINITIONS = FilterDefinitionCollection(
*ComCamFilters,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_ingest.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class LatissIngestTestCase(IngestTestBase, lsst.utils.tests.TestCase):
ingestDir = TESTDIR
file = os.path.join(DATAROOT, "latiss", "raw", "2018-09-20", "3018092000065-det000.fits")
dataIds = [dict(instrument="LATISS", exposure=3018092000065, detector=0)]
filterLabel = lsst.afw.image.FilterLabel(physical="unknown~unknown")
filterLabel = lsst.afw.image.FilterLabel(band="unknown", physical="unknown~unknown")


class Ts3IngestTestCase(IngestTestBase, lsst.utils.tests.TestCase):
Expand Down