Skip to content

Commit

Permalink
Merge pull request #78 from lsst-ts/tickets/DM-29688
Browse files Browse the repository at this point in the history
Tickets/dm 29688
  • Loading branch information
jbkalmbach authored Apr 16, 2021
2 parents c48e152 + 4f5ba93 commit 8bf308e
Show file tree
Hide file tree
Showing 21 changed files with 27,856 additions and 5 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,23 @@ setup -k -r .
1. While testing with the sky images obtained with the auxiliary telescope (localed in `tests/testData/testImages/auxTel`), this package and [cwfs](https://github.com/bxin/cwfs) show the similar result in "onAxis" optical model. However, for the "paraxial" optical model, the results of two packages are different.
2. The main difference comes from the stratege of compensation in the initial loop of solving the TIE. However, it is hard to have a conclusion at this moment because of the low singal-to-noise ratio in test images.

## Test Gen 3 Repository

In the folder `tests/testData/` there is a test repository for tasks that run with the Gen 3 DM middleware.
This repository is the folder `tests/testData/gen3TestRepo` and was built using the files `tests/testData/createGen3TestRepo.sh`.
This script performs the following steps to create the Gen 3 repository:

1. Ingest a reference catalog with the Gen 2 middleware.
This reference catalog is the file `tests/testData/phosimOutput/realComCam/skyComCamInfoRefCatalog.txt` which contains the same information as `skyComCamInfo.txt` in the same folder but formatted to be read in by the Gen 2 middleware as a reference catalog.
A column of g magnitude error is added with a value of 0.1 to fit reference catalog format.
The format of the reference catalog is configured with the file `tests/testData/gen3TestRepo/refCat.cfg`.
2. Convert the Gen 2 repository with the reference catalog into a Gen 3 repository since this is currently the only way to create a Gen 3 reference catalog.
This requires the configuration file `tests/testData/gen3TestRepo/convertRefCat.cfg`.
3. Ingest the raw files in `tests/testData/phosimOutput/realComCam/repackagedFiles`.
4. Clean up the original Gen 2 repository.

Inside the Gen 3 repository there are files for the Gen 3 Butler configuration (`butler.yaml`) and the repository database (`gen3.sqlite3`).

## Build the Document

To build project documentation, run `package-docs build` to build the documentation.
Expand Down
15 changes: 15 additions & 0 deletions doc/content.rst
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,18 @@ This module does the image deblending.
* **DeblendDefault**: Default deblend class.
* **DeblendAdapt**: DeblendDefault child class to do the deblending by the adaptive threshold method.
* **nelderMeadModify**: Do the numerical optimation according to the Nelder-Mead algorithm.

.. _lsst.ts.wep-modules_wep_task:

-------------
wep.task
-------------

This module has the tasks to run WEP as a pipeline with Gen 3 LSST DM middleware.

.. uml:: uml/taskClass.uml
:caption: Class diagram of wep.task

* **GenerateDonutCatalogOnlineTaskConnections**: Connections setup for GenerateDonutCatalogOnlineTask to run in a pipeline with Gen 3 middleware.
* **GenerateDonutCatalogOnlineTaskConfig**: Configuration setup for GenerateDonutCatalogOnlineTask.
* **GenerateDonutCatalogOnlineTask**: Gen 3 middleware task to take pointing information and create a catalog of donut sources in that pointing.
4 changes: 4 additions & 0 deletions doc/uml/taskClass.uml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@startuml
GenerateDonutCatalogOnlineTaskConfig *-- GenerateDonutCatalogOnlineTaskConnections
GenerateDonutCatalogOnlineTask *-- GenerateDonutCatalogOnlineTaskConfig
@enduml
10 changes: 10 additions & 0 deletions doc/versionHistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@
Version History
##################

.. _lsst.ts.wep-1.6.0:

-------------
1.6.0
-------------

* Create new task module
* Add GenerateDonutCatalogOnlineTask.py in task module
* Add `tests/testData/gen3TestRepo` as sample Gen 3 repo for testing

.. _lsst.ts.wep-1.5.9:

-------------
Expand Down
10 changes: 5 additions & 5 deletions python/lsst/ts/wep/cwfs/DonutTemplatePhosim.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def makeTemplate(self, sensorName, defocalType, imageSize):
templateFilename = os.path.join(
phosimTemplateDir, "intra_template-%s.txt" % sensorName
)
templateArray = np.genfromtxt(templateFilename, dtype=np.int)
templateArray = np.genfromtxt(templateFilename, dtype=int)

# Make the template the desired square shape by trimming edges of
# template
Expand All @@ -83,8 +83,8 @@ def makeTemplate(self, sensorName, defocalType, imageSize):
# Find the left and right edges by trimming half pixels from
# left and right.
# Do the same for the top and bottom.
leftEdge = topEdge = np.int(templateTrim / 2)
rightEdge = bottomEdge = np.int(templateSize - (templateTrim - leftEdge))
leftEdge = topEdge = int(templateTrim / 2)
rightEdge = bottomEdge = int(templateSize - (templateTrim - leftEdge))

templateFinal = templateArray[leftEdge:rightEdge, topEdge:bottomEdge]
else:
Expand All @@ -93,8 +93,8 @@ def makeTemplate(self, sensorName, defocalType, imageSize):
templatePad = imageSize - templateSize

# Pad each side by equal amount of pixels
padLeft = padTop = np.int(templatePad / 2)
padRight = padBottom = np.int(imageSize - (templatePad - padLeft))
padLeft = padTop = int(templatePad / 2)
padRight = padBottom = int(imageSize - (templatePad - padLeft))

templateFinal = np.zeros((imageSize, imageSize))
templateFinal[padLeft:padRight, padTop:padBottom] = templateArray
Expand Down
203 changes: 203 additions & 0 deletions python/lsst/ts/wep/task/GenerateDonutCatalogOnlineTask.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
# This file is part of ts_wep.
#
# Developed for the LSST Telescope and Site Systems.
# This product includes software developed by the LSST Project
# (https://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

import typing
import os
import numpy as np
import pandas as pd
import lsst.afw.table as afwTable
import lsst.pex.config as pexConfig
import lsst.pipe.base as pipeBase
import lsst.pipe.base.connectionTypes as connectionTypes
import lsst.obs.lsst as obs_lsst
from lsst.meas.algorithms import ReferenceObjectLoader, LoadReferenceObjectsConfig
from lsst.ts.wep.bsc.WcsSol import WcsSol


class GenerateDonutCatalogOnlineTaskConnections(
pipeBase.PipelineTaskConnections, dimensions=("instrument",)
):
"""
Specify the connections needed for GenerateDonutCatalogOnlineTask.
We need the reference catalogs and will produce donut catalogs for
a specified instrument.
"""

refCatalogs = connectionTypes.PrerequisiteInput(
doc="Reference catalog",
storageClass="SimpleCatalog",
dimensions=("htm7",),
multiple=True,
deferLoad=True,
name="cal_ref_cat",
)
donutCatalog = connectionTypes.Output(
doc="Donut Locations",
dimensions=("instrument",),
storageClass="DataFrame",
name="donutCatalog",
)


class GenerateDonutCatalogOnlineTaskConfig(
pipeBase.PipelineTaskConfig,
pipelineConnections=GenerateDonutCatalogOnlineTaskConnections,
):
"""
Configuration settings for GenerateDonutCatalogOnlineTask. Specifies
pointing information, filter and camera details.
"""

filterName = pexConfig.Field(doc="Reference filter", dtype=str, default="g")
boresightRa = pexConfig.Field(
doc="Boresight RA in degrees", dtype=float, default=0.0
)
boresightDec = pexConfig.Field(
doc="Boresight Dec in degrees", dtype=float, default=0.0
)
boresightRotAng = pexConfig.Field(
doc="Boresight Rotation Angle in degrees", dtype=float, default=0.0
)
cameraName = pexConfig.Field(doc="Camera Name", dtype=str, default="lsstCam")


class GenerateDonutCatalogOnlineTask(pipeBase.PipelineTask):
"""
Create a WCS from boresight info and then use this
with a reference catalog to select sources on the detectors for AOS.
"""

ConfigClass = GenerateDonutCatalogOnlineTaskConfig
_DefaultName = "generateDonutCatalogOnlineTask"

def __init__(self, **kwargs):
super().__init__(**kwargs)

# The filter in the reference catalog we want to use to find sources.
self.filterName = self.config.filterName

# Pointing information to construct the WCS. All values in degrees.
self.boresightRa = self.config.boresightRa
self.boresightDec = self.config.boresightDec
self.boresightRotAng = self.config.boresightRotAng

# Need camera name to get the detectors to use to find X,Y pixel
# values for the sources
self.cameraName = self.config.cameraName

# TODO: Temporary until DM-24162 is closed at which point we
# can remove this
os.environ["NUMEXPR_MAX_THREADS"] = "1"

def filterResults(self, resultsDataFrame):
"""
Run filtering on full set of sources on detector and return
the dataframe with only sources that are acceptable for
wavefront estimation.
Parameters
----------
resultsDataFrame: pandas DataFrame
Full list of sources from reference catalog that appear
on the detector.
Returns
-------
pandas DataFrame
Subset of resultsDataFrame sources that pass required filtering.
"""

# TODO: Here is where we will set up specifications for the sources
# we want to use (i.e., filter on magnitude, blended, etc.).
# For now it just returns all sources.

return resultsDataFrame

def run(
self,
refCatalogs: typing.List[afwTable.SimpleCatalog],
) -> pipeBase.Struct:

refObjLoader = ReferenceObjectLoader(
dataIds=[ref.dataId for ref in refCatalogs],
refCats=refCatalogs,
config=LoadReferenceObjectsConfig(),
)
# This removes the padding around the border of detector BBox when
# matching to reference catalog.
# We remove this since we only want sources within detector.
refObjLoader.config.pixelMargin = 0

# Set up pandas dataframe
fieldObjects = pd.DataFrame([])
ra = []
dec = []
centroidX = []
centroidY = []
det_names = []

# Get camera. Only 'lsstCam' for now.
if self.cameraName == "lsstCam":
camera = obs_lsst.LsstCam.getCamera()
else:
raise ValueError(f"{self.cameraName} is not a valid camera name.")

# Create WCS holder
detWcs = WcsSol(camera=camera)

for detector in camera:
# Set WCS from boresight information
detWcs.setObsMetaData(
self.boresightRa,
self.boresightDec,
self.boresightRotAng,
centerCcd=detector.getName(),
)

try:
# Match detector layout to reference catalog
donutCatalog = refObjLoader.loadPixelBox(
detector.getBBox(), detWcs.skyWcs, filterName=self.filterName
).refCat

# Add matched information to list
ra.append(donutCatalog["coord_ra"])
dec.append(donutCatalog["coord_dec"])
centroidX.append(donutCatalog["centroid_x"])
centroidY.append(donutCatalog["centroid_y"])
det_names.append([detector.getName()] * len(donutCatalog))

except RuntimeError:
continue

# Flatten information from all detector lists and enter into dataframe
fieldObjects["coord_ra"] = np.hstack(ra).squeeze()
fieldObjects["coord_dec"] = np.hstack(dec).squeeze()
fieldObjects["centroid_x"] = np.hstack(centroidX).squeeze()
fieldObjects["centroid_y"] = np.hstack(centroidY).squeeze()
fieldObjects["detector"] = np.hstack(det_names).squeeze()

# Return pandas DataFrame with sources in pointing
# with ra, dec, filter flux, pixel XY information and detector name
# for each source
finalSources = self.filterResults(fieldObjects)

return pipeBase.Struct(donutCatalog=finalSources)
Loading

0 comments on commit 8bf308e

Please sign in to comment.