Skip to content

Full focal plane infrastructure#495

Open
welucas2 wants to merge 36 commits intomainfrom
u/welucas2/full-focal-plane
Open

Full focal plane infrastructure#495
welucas2 wants to merge 36 commits intomainfrom
u/welucas2/full-focal-plane

Conversation

@welucas2
Copy link
Copy Markdown
Collaborator

@welucas2 welucas2 commented Oct 7, 2025

This isn't quite ready yet, but I'd like to get a draft PR in place. This will add to imSim the capability to simulate the full focal plane. Currently, we can only simulate detectors in isolation: for a given set of observation parameters and input, imSim will run through tasks drawing each detector in the list. This neglects any 'crosstalk' between detectors in the form of photons that are generated for one but which (for whatever reason) end up raining down on another.

We're building towards a two-pass full focal plane model which will work like the following:

  1. Pass one will work like a current imSim run, with the addition of an extra output field off_detector_photons. While working on each detector, imSim will gather the photons that end up outside its bounds and write them to file for use in pass two. The other output is the same image that would normally have been produced, of those objects which lie within the detector's bounds and have been drawn on it.
  2. Pass two takes both of those outputs from pass one. While working on a detector, it will read its image from pass one as well as the off-detector photons that were originally created by tasks working on other detectors. In this way, the task working on detector X is able to draw the photons that were originally created while working on the other 188 tasks.

As of the moment there are still things to do here:

  • The current implementation is for the photon pooling pipeline with LSST_PhotonPoolingImage. I'd like to see how easy it would be to implement for the original LSST_Image pipeline, too. This might be something to do later on separately.
    • If not doing now, preventing or providing a warning for users who try to use the off_detector_photons extra output with the original pipeline.
  • Provide a switch when reading off_detector_photons in pass two that refactors the input at the very start, prior to drawing the images.
    • Each task in pass one produces one file. which could potentially contain photons destined for all 188 other detectors. So, to be sure that all photons are captured, not refactoring the files would require each task in pass two to read and work with 188 files.
    • Refactoring would take the 189 files, each containing all the photons originating from a given detector but destined elsewhere, and produce a different set of 189 files, each containing the photons from any origin but destined for a given detector. With this, each task in pass two would only need to read the one off-detector photon file.
  • We should provide template configuration files for users, and probably expand the current imsim-user-instcat-ffp-pass1.yaml and imsim-user-instcat-ffp-pass2.yaml examples.

@welucas2 welucas2 force-pushed the u/welucas2/full-focal-plane branch from e3d3b97 to d711f3e Compare March 16, 2026 17:05
welucas2 and others added 29 commits March 26, 2026 10:42
… -- more general, as we don't want to presume how they got off the detector. Be a bit more general.
…est useful. (Default is now 200 pixels to cover the gap between detectors.)
@welucas2 welucas2 force-pushed the u/welucas2/full-focal-plane branch from 5b71a28 to 2eb3d6e Compare March 26, 2026 10:43
@welucas2 welucas2 force-pushed the u/welucas2/full-focal-plane branch from fa32d92 to f8baa87 Compare March 26, 2026 11:51
@welucas2
Copy link
Copy Markdown
Collaborator Author

This is ready for review now.

For now photon pooling should be used (make sure imsim-config-instcat.yaml or imsim-config-skycat.yaml use template: imsim-config-photon-pooling), as the off-detector photons are gathered from the large photon pools, though if we want it could be added for the original object-by-object pipeline, but I think this would need a little work to expose the photons.

There are two new example configs that should document how the new code is used. These assume instance catalogs are being used, but show the exact same changes that would be needed for a sky catalogs run. This run uses a simple instance catalog that places three stars near the boundary of R22_S11 and R22_S12; after both passes, each of the two images should show the stars that lie within its boundaries as well as the diffraction spikes from the star(s) on the other detector.

The first new config is examples/imsim-user-instcat-ffp-pass1.yaml. This works from imsim-config-instcat.yaml. A first pass full focal plane run is no different from any other single detector run, except that it adds the new off_detector_photons item to the output. All this needs is the name (and directory) of the output file, which is a FITS.

The second new config, examples/imsim-user-instcat-ffp-pass2.yaml, is pretty different. This needs an input.initial_image item (the first pass image for this detector, where we're now going to accumulate those extra photons), an input.off_detector_photons item (which maps in one of two ways to the output.off_detector_photons from the first pass), and for the image.type to be set to LSST_FocalPlaneImage.

(I'm not 100% sure about some of these names. Having two separate items be called off_detector_photons could be confusing? I also thought it might make sense, since the output of that name goes into the input of the same name.)

The input OffDetectorPhotonsLoader needs you to give either but not both of a file_name or a file_pattern. The config shows both, one commented out. If using a file_name, you're simply going to use the photons included that one file. If using a file_pattern, it needs to include two wildcard fields, DETNAME and DETNUM. The code will then try to find up to 188 files matching the pattern given, substituting those fields for detector names and numbers. It's not 189, as it excludes the currect detector.

This assumes you're doing the second pass in one of two ways. If using as many files as match file_pattern, then you've likely generated up to 189 files, one for each first pass detector. You're now using those directly: each second pass job will read 188 files and accumulate whichever of those photons are hitting the current detector. Presumably, that's going to be a pretty small fraction of the total. I wasn't too sure about this system of using DETNAME and DETNUM wildcards, and it might be that setting ranges of detectors or an 'only' list (kind of like the detectors in output) is more user friendly, but I think this is perhaps a little more flexible in terms of the file name structure.

If reading a single file file_name, you're reading the photons from that one file only. I've used this in testing with these two configs, and it hopefully makes sense how it works. In the first pass, generate R22_S11 and R22_S12's images and store off-detector photons. In pass two, work with either one of the detectors and read the off-detector file produced by the other.

(But remember we'd like to refactor the contents of the off-detector files at some point in the workflow. Currently, they contain all the photons which were originally created by a given detector. Refactoring them to instead contain all the photons which are headed for detector N would make the operation much more efficient. In this case you'd specify that single file_name in the config.)

The new image type LSST_FocalPlaneImage is very simple, just taking the photons that were read from file and accumulating them on top of the old image.

Instance and sky catalogs check whether they should drawn ('have ownership'?) of objects a little differently. Previously, it was simply a check on whether the object lay within the bounds of the detector plus edge_pix, by default 100 pixel. I've made that default 200 pixels, which now covers a little more than half of the gap between all pairs of detectors, so no objects can be missed. To make sure that each object is only drawn by one detector, even if if falls in that narrow strip, a fiducial WCS is used to check whether an object is closer to this or to any of the neighboring detectors. It's only drawn by the closest. The fiducial WCS is an option to input.instance_catalog and input.sky_catalog and included in the base config YAMLs as a Batoid WCS. SIP components are stripped away during init.

@welucas2 welucas2 marked this pull request as ready for review March 26, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants