def Transform(obj, jac=(1., 0., 0., 1.), offset=galsim.PositionD(0., 0.), flux_ratio=1., gsparams=None): """A function for transforming either a GSObject or ChromaticObject. This function will inspect its input argument to decide if a Transformation object or a ChromaticTransformation object is required to represent the resulting transformed object. @param obj The object to be transformed. @param jac A list or tuple ( dudx, dudy, dvdx, dvdy ) describing the Jacobian of the transformation. [default: (1,0,0,1)] @param offset A galsim.PositionD giving the offset by which to shift the profile. @param flux_ratio A factor by which to multiply the flux of the object. [default: 1] @param gsparams An optional GSParams argument. See the docstring for GSParams for details. [default: None] @returns a Transformation or ChromaticTransformation instance as appropriate. """ if not (isinstance(obj, galsim.GSObject) or isinstance(obj, galsim.ChromaticObject)): raise TypeError( "Argument to Transform must be either a GSObject or a ChromaticObject." ) elif (hasattr(jac, '__call__') or hasattr(offset, '__call__') or hasattr(flux_ratio, '__call__') or isinstance(obj, galsim.ChromaticObject)): # Sometimes for Chromatic compound types, it is more efficient to apply the # transformation to the components rather than the whole. In particular, this can # help preserve separability in many cases. # Don't transform ChromaticSum object, better to just transform the arguments. if isinstance(obj, galsim.ChromaticSum) or isinstance(obj, galsim.Sum): return galsim.ChromaticSum([ Transform(o, jac, offset, flux_ratio, gsparams) for o in obj.objlist ]) # If we are just flux scaling, then a Convolution can do that to the first element. # NB. Even better, if the flux scaling is chromatic, would be to find a component # that is already non-separable. But we don't bother trying to do that currently. elif (isinstance( obj, galsim.ChromaticConvolution or isinstance(obj, galsim.Convolution)) and np.array_equal(np.asarray(jac).ravel(), (1, 0, 0, 1)) and offset == galsim.PositionD(0., 0.)): first = Transform(obj.objlist[0], flux_ratio=flux_ratio, gsparams=gsparams) return galsim.ChromaticConvolution([first] + [o for o in obj.objlist[1:]]) else: return galsim.ChromaticTransformation(obj, jac, offset, flux_ratio, gsparams) else: return Transformation(obj, jac, offset, flux_ratio, gsparams)
def Add(*args, **kwargs): """A function for adding 2 or more GSObject or ChromaticObject instances. This function will inspect its input arguments to decide if a Sum object or a ChromaticSum object is required to represent the sum of surface brightness profiles. Typically, you do not need to call Add() explicitly. Normally, you would just use the + operator, which returns a Sum: >>> bulge = galsim.Sersic(n=3, half_light_radius=0.8) >>> disk = galsim.Exponential(half_light_radius=1.4) >>> gal = bulge + disk >>> psf = galsim.Gaussian(sigma=0.3, flux=0.3) + galsim.Gaussian(sigma=0.8, flux=0.7) If one of the items is chromatic, it will return a ChromaticSum >>> disk = galsim.Exponential(half_light_radius=1.4) * galsim.SED(sed_file) >>> gal = bulge + disk @param args Unnamed args should be a list of objects to add. @param gsparams An optional GSParams argument. See the docstring for GSParams for details. [default: None] @returns a Sum or ChromaticSum instance as appropriate. """ if len(args) == 0: raise ValueError( "At least one ChromaticObject or GSObject must be provided.") elif len(args) == 1: # 1 argument. Should be either a GSObject or a list of GSObjects if isinstance(args[0], (galsim.GSObject, galsim.ChromaticObject)): args = [args[0]] elif isinstance(args[0], list): args = args[0] else: raise TypeError( "Single input argument must be a GSObject, ChromaticObject or " + "a (possibly mixed) list of them.") # else args is already the list of objects if any([isinstance(a, galsim.ChromaticObject) for a in args]): return galsim.ChromaticSum(*args, **kwargs) else: return Sum(*args, **kwargs)