Skip to content

Commit

Permalink
Merge pull request #655 from GalSim-developers/#218
Browse files Browse the repository at this point in the history
#218 Make everything picklable
  • Loading branch information
rmjarvis committed Apr 17, 2015
2 parents 7fa0391 + eef6d12 commit 7315168
Show file tree
Hide file tree
Showing 151 changed files with 6,598 additions and 3,145 deletions.
32 changes: 27 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,44 @@ Installation Changes
API Changes
-----------

- Changed the name of the `bounds.addBorder()` method to `withBorder` to make
it clearer that the method returns a new Bounds object. (#218)
- Removed (from the python layer) Interpolant2d and InterpolantXY, since we
we have only actually implemented 1-d interpolants. (#218)
- Removed the MultipleImage way of constructing an SBInterpolatedImage, since
we do not use it anywhere, nor are there unit tests for it. The C++ layer
still has the implementation of it if we ever find a need for it. (#218)
- Made the default tolerance for all Interpolants equal to 1.e-4. It already
was for Cubic, Quintic, and Lanczos, which are the ones we normally use,
so this just changes the default for the others. (#218)
- Deprecated the __rdiv__ operator from Bandpass and SED, since we realized
that they did not have any clear use cases. If you have one, please open an
issue, and we can add them back. (#218)
- Made all returned matrices consistently use numpy.array, rather than
numpy.matrix. We had been inconsistent with which type different functions
returned, so now all matrices are numpy.arrays. If you rely on the
numpy.matrix behavior, you should recast with numpy.asmatrix(M). (#218)
- Deprecated CorrelatedNoise.calculateCovarianceMatrix, since it is not used
anywhere, and we think no one really has a need for it. (#630)
- Officially deprecated the methods and functions that had been described as
having been removed or changed to a different name. In fact, many of them
had been still valid, but no longer documented. This was intentional to
allow people time to change their code. Now these methods are officially
deprecated and will emit a warning message if used. (#643)
- Made the classes PositionI, PositionD, and GSParams immutable. It was an
oversight that we failed to make them immutable in version 1.1 when we made
most other GalSim classes immutable. Now rather than write to their various
attributes, you should make a new object. e.g. instead of `p.x = 4` and
`p.y = 5`, you now need to do `p = galsim.PositionD(4,5)`. (#643)
- Made the classes PositionI, PositionD, GSParams, and HSMParams immutable.
It was an oversight that we failed to make them immutable in version 1.1 when
we made most other GalSim classes immutable. Now rather than write to their
various attributes, you should make a new object. e.g. instead of `p.x = 4`
and `p.y = 5`, you now need to do `p = galsim.PositionD(4,5)`. (#218, #643)


New Features
------------

- Added ability to set the zeropoint of a bandpass on construction. (Only
a numeric value; more complicated calculations still need to use the method
`bandpass.withZeropoint()`.) (#218)
- Added ability to set the redshift of an SED on construction. (#218)
- Updated CorrelatedNoise to work with images that have a non-trivial WCS. (#501)
- Added new methods of the image class to simulate detector effects:
inter-pixel capacitance (#555) and image quantization (#558).
Expand Down Expand Up @@ -65,6 +86,7 @@ New Features
Bug Fixes and Improvements
--------------------------

- Fixed a bug in the normalization of SEDs that use `wave_type='A'`. (#218)
- Switched the sign of the angle returned by `CelestialCoord.angleBetween`.
The sign is now positive when the angle as seen from the ground sweeps in
the counter-clockwise direction, which is a more sensible definition than
Expand Down
30 changes: 23 additions & 7 deletions examples/demo7.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
- obj = galsim.Sersic(n, half_light_radius, trunc)
- psf = galsim.OpticalPSF(..., aberrations=aberrations, ...)
- obj = obj.dilate(scale)
- str(obj)
- image.scale = pixel_scale
- obj.drawImage(image, method='fft')
- obj.drawImage(image, method='phot', max_extra_noise, rng)
Expand Down Expand Up @@ -69,6 +70,9 @@ def main(argv):
# To turn off logging:
#logger.propagate = False

# To turn on the debugging messages:
#logger.setLevel(logging.DEBUG)

# Define some parameters we'll use below.

# Make output directory if not already present.
Expand Down Expand Up @@ -200,11 +204,23 @@ def main(argv):
for ipsf in range(len(psfs)):
psf = psfs[ipsf]
psf_name = psf_names[ipsf]
logger.info('psf %d: %s',ipsf+1,psf)
# Note that this implicitly calls str(psf). We've made an effort to give all GalSim
# objects an informative but relatively succinct str representation. Some details may
# be missing, but it should look essentially like how you would create the object.
logger.debug('repr = %r',psf)
# The repr() version are a bit more pedantic in form and should be completely informative,
# to the point where two objects that are not identical should never have equal repr
# strings. As such the repr strings may in some cases be somewhat unwieldy. For instance,
# since we set non-default gsparams in these, the repr includes that information, but
# it is omitted from the str for brevity.
for igal in range(len(gals)):
gal = gals[igal]
gal_name = gal_names[igal]
logger.info(' galaxy %d: %s',igal+1,gal)
logger.debug(' repr = %r',gal)
for i in range(4):
logger.debug('Start work on image %d',i)
logger.debug(' Start work on image %d',i)
t1 = time.time()

# Initialize the random number generator we will be using.
Expand Down Expand Up @@ -240,7 +256,7 @@ def main(argv):
fft_image = image[galsim.BoundsI(1, nx, 1, ny)]
phot_image = image[galsim.BoundsI(nx+3, 2*nx+2, 1, ny)]

logger.debug(' Read in training sample galaxy and PSF from file')
logger.debug(' Read in training sample galaxy and PSF from file')
t2 = time.time()

# Draw the profile
Expand All @@ -252,7 +268,7 @@ def main(argv):
# for illustrative purposes.)
final.drawImage(fft_image, method='fft')

logger.debug(' Drew fft image. Total drawn flux = %f. .flux = %f',
logger.debug(' Drew fft image. Total drawn flux = %f. .flux = %f',
fft_image.array.sum(),final.getFlux())
t3 = time.time()

Expand Down Expand Up @@ -285,17 +301,17 @@ def main(argv):
# image, we need to subtract the mean back off when we are done.
phot_image -= sky_level_pixel

logger.debug(' Added Poisson noise. Image fluxes are now %f and %f',
logger.debug(' Added Poisson noise. Image fluxes are now %f and %f',
fft_image.array.sum(), phot_image.array.sum())
t6 = time.time()

# Store that into the list of all images
all_images += [image]

k = k+1
logger.info('%d: %s * %s, flux = %.2e, hlr = %.2f, ellip = (%.2f,%.2f)',
k,gal_name, psf_name, flux, hlr, gal_shape.getE1(), gal_shape.getE2())
logger.debug(' Times: %f, %f, %f, %f, %f',t2-t1, t3-t2, t4-t3, t5-t4, t6-t5)
logger.info(' %d: flux = %.2e, hlr = %.2f, ellip = (%.2f,%.2f)',
k, flux, hlr, gal_shape.getE1(), gal_shape.getE2())
logger.debug(' Times: %f, %f, %f, %f, %f',t2-t1, t3-t2, t4-t3, t5-t4, t6-t5)

psf_times[ipsf] += t6-t1
psf_fft_times[ipsf] += t3-t2
Expand Down
9 changes: 6 additions & 3 deletions galsim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,11 @@
# To make this seamless with pyfits versions, we add 4 to the astropy version.
from astropy import version as astropy_version
pyfits_version = str( (4 + astropy_version.major) + astropy_version.minor/10.)
pyfits_str = 'astropy.io.fits'
except:
import pyfits
pyfits_version = pyfits.__version__
pyfits_str = 'pyfits'

# Import things from other files we want to be in the galsim namespace

Expand Down Expand Up @@ -126,17 +128,18 @@
from real import RealGalaxy, RealGalaxyCatalog, simReal
from optics import OpticalPSF
from shapelet import Shapelet, ShapeletSize, FitShapelet
from interpolatedimage import Interpolant, Interpolant2d, InterpolantXY
from interpolatedimage import Interpolant
from interpolatedimage import Nearest, Linear, Cubic, Quintic, Lanczos, SincInterpolant, Delta
from interpolatedimage import InterpolatedImage
from compound import Add, Sum, Convolve, Convolution, Deconvolve, Deconvolution
from compound import AutoConvolve, AutoConvolution, AutoCorrelate, AutoCorrelation
from transform import Transform, Transformation

# Chromatic
from chromatic import ChromaticObject, ChromaticAtmosphere, Chromatic, ChromaticSum
from chromatic import ChromaticConvolution, ChromaticDeconvolution, ChromaticAutoConvolution
from chromatic import ChromaticAutoCorrelation
from chromatic import ChromaticOpticalPSF, ChromaticAiry
from chromatic import ChromaticAutoCorrelation, ChromaticTransformation
from chromatic import ChromaticOpticalPSF, ChromaticAiry, InterpolatedChromaticObject
from sed import SED
from bandpass import Bandpass

Expand Down
50 changes: 27 additions & 23 deletions galsim/angle.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,26 @@
"""

def AngleUnit_repr(self):
if self is galsim.radians:
if self == galsim.radians:
return 'galsim.radians'
elif self is galsim.degrees:
elif self == galsim.degrees:
return 'galsim.degrees'
elif self is galsim.hours:
return 'galsim.house'
elif self is galsim.arcmin:
elif self == galsim.hours:
return 'galsim.hours'
elif self == galsim.arcmin:
return 'galsim.arcmin'
elif self is galsim.arcsec:
elif self == galsim.arcsec:
return 'galsim.arcsec'
else:
return 'galsim.AngleUnit(' + str(self.getValue()) + ')'
return 'galsim.AngleUnit(%r)'%self.getValue()
AngleUnit.__repr__ = AngleUnit_repr
AngleUnit.__eq__ = lambda self, other: (
isinstance(other,AngleUnit) and self.getValue() == other.getValue())
AngleUnit.__ne__ = lambda self, other: not self.__eq__(other)
AngleUnit.__hash__ = lambda self: hash(self.getValue())

# Enable pickling
def AngleUnit_getinitargs(self):
return self.getValue()
AngleUnit.__getinitargs__ = AngleUnit_getinitargs
AngleUnit.__getinitargs__ = lambda self: (self.getValue(), )


def get_angle_unit(unit):
Expand Down Expand Up @@ -150,6 +152,15 @@ def get_angle_unit(unit):
of the allowed operations on Angles listed above (e.g., addition/subtraction of Angles,
multiplication of an Angle by a float, but not multiplication of Angles together).
There are convenience function for getting the sin, cos, and tan of an angle, along with
one for getting sin and cos together, which should be more efficient than doing sin and
cos separately:
>>> sint = theta.sin() # equivalent to sint = math.sin(theta.rad())
>>> cost = theta.cos() # equivalent to sint = math.cos(theta.rad())
>>> tant = theta.tan() # equivalent to sint = math.tan(theta.rad())
>>> sint, cost = theta.sincos()
Wrapping
--------
Expand All @@ -163,16 +174,12 @@ def get_angle_unit(unit):
"""

def __str__(self):
angle_rad = self.rad()
return str(angle_rad)+" radians"

def __repr__(self):
angle_rad = self.rad()
return str(angle_rad)+" * galsim.radians"

def __neg__(self):
return -1. * self
Angle.__str__ = lambda self: str(self.rad()) + ' radians'
Angle.__repr__ = lambda self: 'galsim.Angle(%r, galsim.radians)'%self.rad()
Angle.__eq__ = lambda self, other: isinstance(other,Angle) and self.rad() == other.rad()
Angle.__ne__ = lambda self, other: not self.__eq__(other)
Angle.__neg__ = lambda self: -1. * self
Angle.__hash__ = lambda self: hash(repr(self))

def _make_dms_string(decimal, sep):
if decimal >= 0:
Expand Down Expand Up @@ -246,9 +253,6 @@ def dms(self, sep=":"):
d = self.wrap() / galsim.degrees
return _make_dms_string(d,sep)

Angle.__str__ = __str__
Angle.__repr__ = __repr__
Angle.__neg__ = __neg__
Angle.hms = hms
Angle.dms = dms

Expand Down
Loading

0 comments on commit 7315168

Please sign in to comment.