I’m in the process of designing a full-field optical PSF model for the LSST stack. One of the necessary ingredients for this is a model of the pupil obscuration function, i.e., which parts of the pupil (more-or-less the primary mirror) are visible and reflect sky as opposed to struts, camera, etc. This boolean function will vary with position on the focal plane and the camera rotator angle, and it is probably a good idea to make the size and resolution of the output array configurable as well.
Looking through the available LSST packages, and talking/slacking with @KSK, @jbosch, and @RHL, I think
afw.cameraGeom.Camera looks like the natural home for such a product. My understanding is that for a given data repository, cameras are uniquely accessible from the butler (i.e., there is exactly one
Camera per data repo). So the PSF modeling code could access the
Pupil through the repo
Camera which is accessible through the
Butler. Alternatively, the
Pupil could exist at the same level as the
Camera instead of being an attribute thereof, and directly accessible by the
Butler. I personally favor the former approach though as it prevents enabling incompatible
I have a few additional implementation questions:
Should the pupil obscuration function be persistable? The pupil model I have in mind consists of set operations on various 2D geometric objects – circles, rays-with-finite-width, rectangles, … The parameters of each geometric object depend (linearly for now) on the focal plane position and trigonometrically on the camera rotator angle, which means it may be possible to create a generic
PupilConfigformat that could be persisted, and used to represent different cameras, or possibly different levels of complexity for a given camera. I’m not convinced at the moment, however, that this is actually worth the effort. It would be much simpler to just implement a specific class for each camera (all derived from the same abstract base class), and then attach that to the
I think it makes sense to split the input arguments into rotator angle, size/scale params (which will be held constant for a given exposure) and focal plane x/y which, of course, vary object to object. So it may make sense to attach a camera-specific
Cameraobject, which has a
getPupil(VisitInfo, size, scale)method that returns a
Pupilobject itself would then be callable or have a callable method as a function of focal plane x/y, returning a boolean array.
As for actually attaching the
Camera, I see that, at least for HSC in obs_subaru, the
Camerais constructed though the chain
So one possibility would be to add a
pupilFactory kwarg to
Camera.__init__ and make sure
makeCameraFromPath (and any other camera factories) use it.
CameraMapper could have a class variable
PupilFactoryClass (similar to
MakeRawVisitInfoClass) pointing to a default
PupilFactory (possibly the ABC) and
HscMapper.PupilFactoryClass could override this by pointing to
HscPupilFactory. Then when
_makeCamera gets called, it uses
self.PupilFactoryClass to pass to
Also, does any of this require an RFC?