GalSim-developers/GalSim — pull request #538 by rmjarvis (2014-04-29 00:08:32+00:00)
Title: #535 New drawImage method

This is one last API-changing branch that we would like to get into the next release so we can have our all API changes done at one time. I think (hope) that the API will be rather stable after this one. (Aside from new features of course.)

Because of that, I hope to get some feedback from some of our more active users about the design change. @dkirkby @reikonakajima @jmeyers314 @TallJimbo @msimet @joezuntz (Anyone, feel free to add pings of anyone else you think ought to check this out.)

This PR addresses two problems with our current API with respect to drawing images. The main one is that the concept of convolving with a Pixel to integrate a profile over the pixel response seems to be rather counter-intuitive for a lot of users. Despite all the places we try to explain it -- the docs, the example scripts, etc. -- a very common failure mode for newbies is to neglect to convolve by a Pixel before drawing.

The other one is a rather minor inconvenience that `draw` and `drawShoot` are nearly completely parallel, and yet they are two different functions and work a bit differently, since `drawShoot` implicitly convolves by a Pixel for you via the shooting process, and `draw` does not. This ends up in a reasonable amount of code duplication in various places that need to keep track of whether to convolve with a Pixel or not and then call a different function at the end.

To remedy both of these points, I combined the two functions (`draw` and `drawShoot`) into a single function, `drawImage`. The two different rendering methods are set by a parameter `method='fft'` or `method='phot'`. Furthermore, in _both_ cases, the way to call the function is with an object that has _not_ been convolved by a Pixel. The `drawImage` command does that for you when `method='fft'`.

This third way of doing the convolution is via direct integration in real space. For that, there is now `method='real_space'`. And `method='auto'` is the default, which selects between `method='real_space'` and `method='fft'` smartly depending on whether the profile has hard edges. i.e. the same determination that is done by Convolution when `real_space = None` (the default).

In addition, since sometimes you don't want to convolve by a Pixel, there is `method='no_pixel'`, which works the way the old `draw` command worked.

All of the above use what we had been calling `normalization='flux'`. The surface brightness normalization doesn't really make much sense (IMHO) for photon shooting, so I just have `method='sb'` that works the way the old `draw(normalization='sb')` worked. I think that should cover all the use cases for rendering a surface brightness profile directly, but please correct me if you want/need the equivalent of `drawShoot(normalization='sb')` to be preserved in the new syntax.

Some other changes I made along the way:
- Of course I updated the examples and such to the new format, but I specifically did not edit the unit tests to change to the new drawImage calls. So the old methods still work for now, and are not even officially deprecated yet. This follows how we've been rolling these API changes out in this release. The old stuff should still work for now to ease the transition of legacy code.
- I added unit tests the check the consistency of the new draw methods.
- I did have to edit the chromatic tests slightly because they explicitly called ChromaticObject.draw to get the base class implementation. But that didn't work after my change, so for those call, I did switch to drawImage.
- I added a `setup_only` parameter to `drawImage` that the Chromatic objects can use to setup the image appropriately without duplicating a lot of the internals of the draw command as they had been doing.
- I think the changes in the Chromatic classes' draw commands will work with photon shooting now, which hadn't been implemented. But I didn't test it.
- I switched from the GKP abscissae that start with 1 point to the ones that start with 10 points, because I discovered that the real-space integration was significantly more accurate with that.
- I also dropped the default GSParams.realspace_relerr value to 1.e-4. It's not much slower, and it also helped a bit with the accuracy (but not as much as the 10 point change).
- I made a couple changes to the unit tests that failed because the integrals got more accurate.
- The config `image.draw_method` item now fully matches the drawImage commands `method` parameter. In fact the names for the different `method` options were chosen to follow what had been used by the config stuff.
- I changed the `output.psf.real_space = True` config option to `output.psf.draw_method = real_space`. i.e. it mirrors the `image.draw_method` option now.