Ticket #793 (closed defect: fixed)

Opened 10 years ago

Last modified 7 years ago

Convolution with Psf model yields inverted images

Reported by: becker Owned by: rhl
Priority: normal Milestone:
Component: meas_algorithms Keywords:
Cc: ktl, rowen@…, acbecker@… Blocked By: #833
Blocking: Project: LSST
Version Number: meas_algorithms 3.0.8
How to repeat:
setup meas_algorithms
>>> import buildPsf
>>> mo = buildPsf.MO()
>>> mo.doit("729994p_12_data")
>>> cmi = mo.exposure.getMaskedImage().Factory(mo.exposure.getMaskedImage().getDimensions())
>>> mo.psf.convolve(cmi, mo.exposure.getMaskedImage(), True, buildPsf.afwImage.MaskU.getMaskPlane("EDGE"))
>>> cmi.getImage().get(216, 3095)

Looking at the result (cmi) the stars are bright, so I don't see the inversion.

Description (last modified by rhl) (diff)

Generation of a Psf using the attached script yields a spatially varying Psf model that, when convolved with the input image, yields an inverted image.

The original description was as follows, but RHL thinks that it superceded by the how-to-repeat case --- although he can't get it to fail.

Russ will flesh out this ticket with the input and output images. Attached is the code used to make the Psf.

This ticket is meant to get the ball rolling on an example failure mode.

The script is run like:

python ~/python/LSST/buildPsf.py cal-53535-i-797722_1


buildPsf.py (13.8 KB) - added by becker 10 years ago.
Script used to build the Psf
readPsf.py (977 bytes) - added by becker 10 years ago.
Script to read in the persisted Psf model
psfModel.xml (22.3 KB) - added by rowen 10 years ago.
The PSF model for image 729994p amplifier 12

Change History

Changed 10 years ago by becker

Script used to build the Psf

Changed 10 years ago by becker

Script to read in the persisted Psf model

Changed 10 years ago by rowen

The PSF model for image 729994p amplifier 12

comment:1 Changed 10 years ago by rowen

A sample image 729994p amplifier 12 is now checked into DMS/testdata/meas_algorithmdata/trunk/72994p_12_data_*.fits The measured PSF model has been attached to this ticket. This PSF model has a spatially varying LinearCombinationKernel with two basis kernels: the first looks like a normal star-like PSF and the second looks rather like noise. If the PSF model is convolved with the masked image, the resulting image plane looks inverted. I think it must be the spatial model causing the inversion (e.g. incorrect spatial coefficients) because I can't see how to get it from the basis kernels.

comment:2 Changed 10 years ago by rhl

  • Version Number set to meas_algorithms 3.0.8
  • How to repeat modified (diff)
  • Description modified (diff)

I moved the files to /lsst/DC3root/ticketFiles/793, but I don't think that the provided scripts reproduce the problem. The how-to-repeat describes how to run the provided test case, but the resulting image isn't inverted.

comment:3 Changed 10 years ago by rowen

I added two files to /lsst/DC3root/ticketFiles/793:

  • convolveImageWithPsf.py which demonstrates that convolution of the image with the PSF model results in an inverted output image.
  • problemPsfModel.xml: a copy of psfModel.xml (after I confirmed that it was identical to the copy I already had), so one can freely create new psf models without disturbing the original).

I also note that convolution takes 70 seconds using the 4.1.2 stack (the 4.3 stack appears to be broken at the moment). That is 30 seconds for each basis kernel.

comment:4 Changed 10 years ago by rowen

  • Cc ktl added

It appears that the PSF model is not surviving its round trip. I added file doit.py which strongly suggests this. To use it first setup meas_algorithms (as for any of these files). It runs code from buildPsf.py to build a psf; that code persists the PSF to psfModel.xml (I have verified that the file is written, but not carefully checked the code that writes it). doit.py then reads in the persisted psf and prints the size of the two kernels -- which are different (15x15 for the original PSF model's kernel, 21x21 for the unpersisted version).

By the way, Robert, could you please set these files group writable (unless you are protecting them)?

comment:5 Changed 10 years ago by ktl

The PSF in mo.psf, which is the one whose size is printed out first by doit.py, is a 15x15 double gaussian used for smoothing during detection. It is not the PSF that is written out in psfModel.xml, which is a 21x21 PCA PSF built as a local variable (not a member variable) in MO.buildPsf() from the source list. Accordingly, it doesn't (yet) look like persistence is the problem here.

comment:6 Changed 10 years ago by becker

What is the state of this ticket - Is the psf in psfModel.xml correct? If so, does it yield an inverted image when convolving the science image?

comment:7 Changed 10 years ago by becker

Looking at the script "doit.py", it does look like this is looking at the wrong Psf.

mo = buildPsf.MO()
psfModel = mo.psf

only returns a basic Gaussian used for object detection, the objects from which the final Psf is built.

    def readData(self, fileName):
        FWHM = 5
        self.psf = algorithms.createPSF("DoubleGaussian", 15, 15, FWHM/(2*sqrt(2*log(2))))

The Psf persisted in psfModel.xml is derived from self.buildPsf().

I think this problem still stands.

comment:8 Changed 10 years ago by rhl

I am still confused. Can someone please write a script that can be run to illustrate this problem? When I looked at it, I could not reproduce the problem.

comment:9 Changed 10 years ago by becker

cd /lsst/DC3root/ticketFiles/793
python convolveImageWithPsf.py

comment:10 Changed 10 years ago by rhl

  • Status changed from new to assigned
  • Owner changed from rhl to becker

I edited convolveImageWithPsf.py to be callable from python and to use a much smaller image, but indeed it shows the issue.

If you run

import convolveImageWithPsf; mi, psf, cmi = convolveImageWithPsf.run(True)

you'll see a mosaic of the PSF's kernel instantiated at 4 positions in the image (without normalisation) on ds9 and indeed it's negative, and its amplitude varies widely.

So the next question is, "where did this PSF come from?". Another question is, "Should convolving with a spatially varying PSF guarantee the correct normalisation at all points?".

Let's answer the first first. Can someone (Andy?) add some code to this ticket how-to-repeat that calculates this PSF? And does the non-persisted PSF show the same bad behaviour --- i.e. is the problem in meas/algorithms or in the PSF persistence code?

comment:11 Changed 10 years ago by becker

Apply the attached script to the data in



python buildPsf.py 729994p_12_data

comment:12 Changed 10 years ago by becker

I was working on this during the phone con and before I got called off, I made some progress. Basically, if I modify the script buildPsf.py to say...

    def buildPsf(self, fluxLim=1e4):
        persistence.persist(psf, storageList, dafBase.PropertySet())

        # and do a convolution
        outMi = afwImage.MaskedImageF(self.exposure.getMaskedImage().getDimensions())
        afwMath.convolve(outMi, self.exposure.getMaskedImage(), psf.getKernel(), False)

I get an image that is *not* entirely negatively valued, although the variance is 1e9. The spatial variation in the convolved image is also suspect (i.e. wrong). This suggests 2 things :

  • The psf does have some problems
  • The psf is being (un)persisted incorrectly.

comment:13 Changed 10 years ago by ktl

I have compared the LinearCombinationKernel toString() values and the component FixedKernel image values for the pre-persistence pcaPsf created by buildPsf.py and the pcaPsf retrieved by code identical to that in readPsf.py. They are identical. Is there anything else that could differ between these two that could cause the observed behavior? If not, I must claim that the problem lies somewhere other than persistence.

comment:14 Changed 10 years ago by rowen

I added roBuildPsf.py which is a variant of buildPsf.py that shows the problem more clearly.

MO creates two psfs: a double gaussian used to smooth and interpolate out cosmic rays. That is the one that was saved as self.psf and it works as expected. (It is also persisted as "smoothingPsf.xml" and the smoothed image as "smoothedImage" but they aren't interesting).

MO.buildPsfModel (formerly MO.buildPsf) creates a new psf named self.psfModel (formerly it was not saved as an attribute of MO). This one is persisted. It is convolved with the input exposure before being persisted and after being unpersisted. The result of convolving these with the input image are saved as imageConvolvedWithPsfModel and imageConvolvedWithUnpersistedPsfModel. These are identical to a casual inspection (suggesting that there is no issue with persistence) and both show the bug that this PR is about.

It appears to me that the psf returned by Psf.getPsf is crazy in this case, for whatever reason.

comment:15 Changed 10 years ago by rhl

  • Blocked By 833 added

comment:16 Changed 10 years ago by rhl

The problem here is that the PSFs are not guaranteed to be normalised. In fact, it's quite hard (more accurately, impossible) to guarantee that a LinearCombinationKernel is properly normalised.

I'm not sure why we were convolving an image with the full PSF (as opposed to e.g. a Gaussian approximation), but it should work.

I believe that the correct fix is to give the function convolveLinear a normalize flag (like convolve); I have filed a ticket, #833, to request this.

comment:17 Changed 10 years ago by becker

Can this ticket be closed?

comment:18 Changed 10 years ago by becker

  • Owner changed from becker to rhl

comment:19 Changed 9 years ago by rhl

  • Status changed from assigned to closed
  • Resolution set to fixed

comment:20 Changed 7 years ago by robyn

  • Milestone DC3b Apps NIghtly Processing deleted

Milestone DC3b Apps NIghtly Processing deleted

Note: See TracTickets for help on using tickets.