Skip to content

Commit

Permalink
tidied up the base.py post merge
Browse files Browse the repository at this point in the history
  • Loading branch information
barnabytprowe committed Aug 20, 2012
1 parent 672b2f6 commit 06f08a2
Showing 1 changed file with 71 additions and 161 deletions.
232 changes: 71 additions & 161 deletions galsim/base.py
Expand Up @@ -854,7 +854,7 @@ class AtmosphericPSF(GSObject):
@param fwhm FWHM of the Kolmogorov PSF.
Either fwhm or lam_over_r0 (and only one) must be specified.
@param interpolant optional keyword for specifying the interpolation scheme [default =
galsim.InterpolantXY(galsim.Lanczos(5, conserve_flux=True, tol=1.e-4))]
galsim.InterpolantXY(galsim.Quintic(tol=1.e-4))]
@param oversampling optional oversampling factor for the SBInterpolatedImage table
[default = 1.5], setting oversampling < 1 will produce aliasing in the
PSF (not good).
Expand Down Expand Up @@ -889,7 +889,8 @@ def _set_half_light_radius(self, value):

# Defining the optional parameters interpolant and oversampling
interpolant = descriptors.SimpleParam(
"interpolant", default=None, group="optional", doc="Real space interpolant instance (2D).")
"interpolant", default=None, group="optional",
doc="Real space InterpolantXY instance (2D).")

oversampling = descriptors.SimpleParam(
"oversampling", default=1.5, group="optional",
Expand All @@ -912,8 +913,8 @@ def _SBInitialize(self):
array_shape=(npix, npix), dx=dx_lookup, lam_over_r0=self.lam_over_r0, flux=self.flux)
# Run checks on the interpolant and build default if None
if self.interpolant is None:
lan5 = galsim.Lanczos(5, conserve_flux=True, tol=1e-4)
self.interpolant = galsim.InterpolantXY(lan5)
quintic = galsim.Quintic(tol=1e-4)
self.interpolant = galsim.InterpolantXY(quintic)
else:
if isinstance(self.interpolant, galsim.InterpolantXY) is False:
raise RuntimeError('Specified interpolant is not an InterpolantXY!')
Expand All @@ -922,6 +923,12 @@ def _SBInitialize(self):
GSObject.__init__(
self, galsim.SBInterpolatedImage(atmoimage, self.interpolant, dx=dx_lookup))

# The above procedure ends up with a larger image than we really need, which
# means that the default stepK value will be smaller than we need.
# Thus, we call the function calculateStepK() to refine the value.
self.SBProfile.calculateStepK()
self.SBProfile.calculateMaxK()

# --- Public Class methods ---
def __init__(self, lam_over_r0=None, fwhm=None, interpolant=None, oversampling=1.5, flux=1.):

Expand Down Expand Up @@ -1036,6 +1043,36 @@ def _set_fwhm(self, value):
raise NotImplementedError(
"FWHM support not implemented for Airy objects with non-zero obscuration.")

# Then we define the fwhm descriptor with reference to these getter/setter functions
fwhm = descriptors.GetSetFuncParam(
getter=_get_fwhm, setter=_set_fwhm, group="size",
doc="FWHM, implemented for Airy function objects with obscuration=0.")

# --- Defining the function used to (re)-initialize the contained SBProfile as necessary ---
# *** Note a function of this name and similar content MUST be defined for all GSObjects! ***
def _SBInitialize(self):
GSObject.__init__(
self, galsim.SBAiry(
lam_over_D=self.lam_over_D, obscuration=self.obscuration, flux=self.flux))

# --- Public Class methods ---
def __init__(self, lam_over_D=None, half_light_radius=None, fwhm=None, obscuration=0., flux=1.):

self._setup_data_store() # Used for storing parameter data, accessed by descriptors

# Set obscuration. The latter must be set before the sizes to raise NotImplementedError
# expections if half_light_radius is used with obscuration!=0.
self.obscuration = obscuration

# Use _parse_sizes() to initialize size parameters
_parse_sizes(
self, label="Airy", lam_over_D=lam_over_D, half_light_radius=half_light_radius,
fwhm=fwhm)

# Set the flux
self.flux = flux


class Kolmogorov(GSObject):
"""@brief GalSim Kolmogorov, which has an SBKolmogorov in the SBProfile attribute.
Expand All @@ -1044,7 +1081,7 @@ class Kolmogorov(GSObject):
Initialization
--------------
@code
psf = galsim.Kolmogorov(lam_over_r0)
psf = galsim.Kolmogorov(lam_over_r0, flux=1.)
@endcode
Initialized psf as a galsim.Kolmogorov() instance.
Expand All @@ -1060,85 +1097,44 @@ class Kolmogorov(GSObject):
@param half_light_radius Half-light radius of the Kolmogorov PSF.
One of lam_over_r0, fwhm and half_light_radius (and only one)
must be specified.
@param flux optional flux value [default = 1]
@param flux optional flux value [default = 1].
"""

# The FWHM of the Kolmogorov PSF is ~0.976 lambda/r0 (e.g., Racine 1996, PASP 699, 108).
# In SBKolmogorov.cpp we refine this factor to 0.975865
_fwhm_factor = 0.975865
# Similarly, SBKolmogorov calculates the relation between lambda/r0 and half-light radius
_hlr_factor = 0.554811

def __init__(self, lam_over_r0=None, fwhm=None, half_light_radius=None, flux=1.):
if fwhm is not None :
if lam_over_r0 is not None or half_light_radius is not None:
raise TypeError(
"Only one of lam_over_r0, fwhm, and half_light_radius may be " +
"specified for Kolmogorov")
else:
lam_over_r0 = fwhm / Kolmogorov._fwhm_factor
elif half_light_radius is not None:
if lam_over_r0 is not None:
raise TypeError(
"Only one of lam_over_r0, fwhm, and half_light_radius may be " +
"specified for Kolmogorov")
else:
lam_over_r0 = half_light_radius / Kolmogorov._hlr_factor
elif lam_over_r0 is None:
raise TypeError(
"One of lam_over_r0, fwhm, or half_light_radius must be " +
"specified for Kolmogorov")

GSObject.__init__(self, galsim.SBKolmogorov(lam_over_r0=lam_over_r0, flux=flux))

def getLamOverR0(self):
"""Return the lam_over_r0 parameter of this Kolmogorov profile.
"""
return self.SBProfile.getLamOverR0()

def getFWHM(self):
"""Return the FWHM of this Kolmogorov profile
"""
return self.SBProfile.getLamOverR0() * Kolmogorov._fwhm_factor

def getHalfLightRadius(self):
"""Return the half light radius of this Kolmogorov profile
"""
return self.SBProfile.getLamOverR0() * Kolmogorov._hlr_factor

# Defining the natural size parameter lam_over_r0
lam_over_r0 = descriptors.SimpleParam(
name="lam_over_r0", group="size", default=None,
doc="Lambda / r0, kept consistent with the other size atttributes.")

class Pixel(GSObject):
"""@brief GalSim Pixel, which has an SBBox in the SBProfile attribute.
"""
def __init__(self, xw, yw=None, flux=1.):
if yw is None:
yw = xw
GSObject.__init__(self, galsim.SBBox(xw=xw, yw=yw, flux=flux))
# Then define the fwhm and half light radius via calculated scaling factors from lam_over_r0
fwhm = descriptors.GetSetScaleParam(
name="fwhm", root_name="lam_over_r0", factor=_fwhm_factor, group="size",
doc="FWHM, kept consistent with the other size attributes.")

# Then we define the fwhm descriptor with reference to these getter/setter functions
fwhm = descriptors.GetSetFuncParam(
getter=_get_fwhm, setter=_set_fwhm, group="size",
doc="FWHM, implemented for Airy function objects with obscuration=0.")
half_light_radius = descriptors.GetSetScaleParam(
name="half_light_radius", root_name="lam_over_r0", factor=_hlr_factor, group="size",
doc="Half light radius, kept consistent with the other size attributes.")

# --- Defining the function used to (re)-initialize the contained SBProfile as necessary ---
# *** Note a function of this name and similar content MUST be defined for all GSObjects! ***
def _SBInitialize(self):
GSObject.__init__(
self, galsim.SBAiry(
lam_over_D=self.lam_over_D, obscuration=self.obscuration, flux=self.flux))

GSObject.__init__(self, galsim.SBKolmogorov(lam_over_r0=self.lam_over_r0, flux=self.flux))

# --- Public Class methods ---
def __init__(self, lam_over_D=None, half_light_radius=None, fwhm=None, obscuration=0., flux=1.):
def __init__(self, lam_over_r0=None, fwhm=None, half_light_radius=None, flux=1.):

self._setup_data_store() # Used for storing parameter data, accessed by descriptors

# Set obscuration. The latter must be set before the sizes to raise NotImplementedError
# expections if half_light_radius is used with obscuration!=0.
self.obscuration = obscuration

# Use _parse_sizes() to initialize size parameters
_parse_sizes(
self, label="Airy", lam_over_D=lam_over_D, half_light_radius=half_light_radius,
fwhm=fwhm)
self, label="Kolmogorov", lam_over_r0=lam_over_r0, fwhm=fwhm,
half_light_radius=half_light_radius)

# Set the flux
self.flux = flux
Expand Down Expand Up @@ -1172,19 +1168,17 @@ class OpticalPSF(GSObject):
@param coma1 coma along x in units of incident light wavelength.
@param coma2 coma along y in units of incident light wavelength.
@param spher spherical aberration in units of incident light wavelength.
@param circular_pupil adopt a circular pupil? Alternative is square
@param circular_pupil adopt a circular pupil? Alternative is square.
@param obscuration linear dimension of central obscuration as fraction of pupil linear
dimension, [0., 1.) [default = 0.]
dimension, [0., 1.) [default = 0.].
@param interpolant optional keyword for specifying the interpolation scheme [default =
galsim.InterpolantXY(galsim.Lanczos(5, conserve_flux=True, tol=1.e-4))].
@param interpolantxy optional keyword for specifying the interpolation scheme [default =
galsim.InterpolantXY(galsim.Quintic(tol=1.e-4))].
@param oversampling optional oversampling factor for the SBInterpolatedImage table
[default = 1.5], setting oversampling < 1 will produce aliasing in the
PSF (not good).
@param pad_factor additional multiple by which to zero-pad the PSF image to avoid folding
compared to what would be required for a simple Airy [default = 1.5].
Note that padFactor may need to be increased for stronger aberrations,
Note that pad_factor may need to be increased for stronger aberrations,
i.e. those larger than order unity.
@param flux total flux of the profile [default flux=1.]
Note that pad_factor may need to be increased for stronger aberrations,
Expand Down Expand Up @@ -1268,33 +1262,22 @@ def _SBInitialize(self):

# If interpolant not specified on input, use a high-ish n lanczos
if self.interpolant == None:
lan5 = galsim.Lanczos(5, conserve_flux=True, tol=1.e-4)
self.interpolant = galsim.InterpolantXY(lan5)
if interpolantxy == None:
lan5 = galsim.Quintic(tol=1.e-4)
self.Interpolant2D = galsim.InterpolantXY(lan5)
quintic = galsim.Quintic(tol=1.e-4)
self.interpolant = galsim.InterpolantXY(quintic)
else:
if isinstance(self.interpolant, galsim.InterpolantXY) is False:
raise RuntimeError('Specified interpolant is not an InterpolantXY!')

# Initialize the SBProfile
GSObject.__init__(
self, galsim.SBInterpolatedImage(optimage, self.interpolant, dx=dx_lookup))
self.Interpolant2D = interpolantxy
GSObject.__init__(self, galsim.SBInterpolatedImage(optimage, self.Interpolant2D,
dx=dx_lookup))

# The above procedure ends up with a larger image than we really need, which
# means that the default stepK value will be smaller than we need.
# Thus, we call the function calculateStepK() to refine the value.
self.SBProfile.calculateStepK()
self.SBProfile.calculateMaxK()

def getHalfLightRadius(self):
# The half light radius is a complex function for aberrated optical PSFs, so just give
# up gracelessly...
raise NotImplementedError("Half light radius calculation not implemented for OpticalPSF "
+"objects.")

# --- Public Class methods ---
def __init__(self, lam_over_D, defocus=0., astig1=0., astig2=0., coma1=0., coma2=0., spher=0.,
circular_pupil=True, obscuration=0., interpolant=None, oversampling=1.5,
Expand Down Expand Up @@ -1520,46 +1503,7 @@ def __init__(self, half_light_radius=None, flux=1.):
# Set the flux
self.flux = flux


def __init__(self, lam_over_r0=None, fwhm=None, interpolantxy=None, oversampling=1.5):
# The FWHM of the Kolmogorov PSF is ~0.976 lambda/r0 (e.g., Racine 1996, PASP 699, 108).
if lam_over_r0 is None :
if fwhm is not None :
lam_over_r0 = fwhm / 0.976
else:
raise TypeError("Either lam_over_r0 or fwhm must be specified for AtmosphericPSF")
else :
if fwhm is None:
fwhm = 0.976 * lam_over_r0
else:
raise TypeError(
"Only one of lam_over_r0 and fwhm may be specified for AtmosphericPSF")
dx_lookup = .5 * fwhm / oversampling
# Fold at 10 times the FWHM
stepk_kolmogorov = np.pi / (10. * fwhm)
# Odd array to center the interpolant on the centroid. Might want to pad this later to
# make a nice size array for FFT, but for typical seeing, arrays will be very small.
npix = 1 + 2 * (np.ceil(np.pi / stepk_kolmogorov)).astype(int)
atmoimage = galsim.atmosphere.kolmogorov_psf_image(array_shape=(npix, npix), dx=dx_lookup,
lam_over_r0=lam_over_r0)
if interpolantxy == None:
lan5 = galsim.Quintic(tol=1e-4)
self.Interpolant2D = galsim.InterpolantXY(lan5)
else:
self.Interpolant2D = interpolantxy
GSObject.__init__(self, galsim.SBInterpolatedImage(atmoimage, self.Interpolant2D,
dx=dx_lookup))
# The above procedure ends up with a larger image than we really need, which
# means that the default stepK value will be smaller than we need.
# Thus, we call the function calculateStepK() to refine the value.
self.SBProfile.calculateStepK()
self.SBProfile.calculateMaxK()

def getHalfLightRadius(self):
# TODO: This seems like it would not be impossible to calculate
raise NotImplementedError("Half light radius calculation not yet implemented for "+
"Atmospheric PSF objects (could be though).")


class RealGalaxy(GSObject):
"""@brief Class describing real galaxies from some training dataset.
Expand Down Expand Up @@ -1988,8 +1932,11 @@ def __init__(self, farg):
"size" : ("half_light_radius",),
"optional" : ("flux",) },
"Airy": { "required" : () ,
"size" : ("lam_over_D",) ,
"size" : ("lam_over_D",),
"optional" : ("obscuration", "flux",)},
"Kolmogorov": { "required" : () ,
"size" : ("lam_over_r0", "fwhm", "half_light_radius"),
"optional" : ("flux",)},
"Pixel": { "required" : ("xw", "yw",),
"size" : (),
"optional" : ("flux",) },
Expand All @@ -2006,43 +1953,6 @@ def __init__(self, farg):
"optional" : ("real_galaxy_catalog", "index", "ID", "random",
"uniform_deviate", "interpolant")}
}
object_param_dict = {"Gaussian": { "required" : (),
"size" : ("half_light_radius", "sigma", "fwhm",),
"optional" : ("flux",) },
"Moffat": { "required" : ("beta",),
"size" : ("half_light_radius", "scale_radius",
"fwhm",),
"optional" : ("trunc", "flux",) },
"Sersic": { "required" : ("n",) ,
"size" : ("half_light_radius",),
"optional" : ("flux",) },
"Exponential": { "required" : (),
"size" : ("half_light_radius", "scale_radius"),
"optional" : ("flux",) },
"DeVaucouleurs": { "required" : (),
"size" : ("half_light_radius",),
"optional" : ("flux",) },
"Airy": { "required" : () ,
"size" : ("D",) ,
"optional" : ("obs", "flux",)},
"Kolmogorov": { "required" : () ,
"size" : ("lam_over_r0", "fwhm", "half_light_radius") ,
"optional" : ("flux",)},
"Pixel": { "required" : ("xw", "yw",),
"size" : (),
"optional" : ("flux",) },
"OpticalPSF": { "required" : (),
"size" : ("lam_over_D",),
"optional" : ("defocus", "astig1", "astig2", "coma1",
"coma2", "spher", "circular_pupil",
"interpolantxy", "dx", "oversampling",
"pad_factor") },
"DoubleGaussian": { "required" : (),
"size" : ("sigma1, sigma2, fwhm1, fwhm2",),
"optional" : () },
"AtmosphericPSF": { "required" : (),
"size" : ("fwhm", "lam_over_r0"),
"optional" : ("dx", "oversampling") } }


class AttributeDict(object):
Expand Down

0 comments on commit 06f08a2

Please sign in to comment.