def get_zeropadding(im, bounds): # Number of pixels on each axis outside the image bounds delta_x_min, delta_x_max, delta_y_min, delta_y_max = 0, 0, 0, 0 if (bounds.ymin < im.bounds.ymin): delta_y_min = im.bounds.ymin - bounds.ymin bounds = galsim.BoundsI(ymin=im.bounds.ymin, ymax=bounds.ymax, xmin=bounds.xmin, xmax=bounds.xmax) if (bounds.ymax > im.bounds.ymax): delta_y_max = bounds.ymax - im.bounds.ymax bounds = galsim.BoundsI(ymin=bounds.ymin, ymax=im.bounds.ymax, xmin=bounds.xmin, xmax=bounds.xmax) if (bounds.xmin < im.bounds.xmin): delta_x_min = im.bounds.xmin - bounds.xmin bounds = galsim.BoundsI(ymin=bounds.ymin, ymax=bounds.ymax, xmin=im.bounds.xmin, xmax=bounds.xmax) if (bounds.xmax > im.bounds.xmax): delta_x_max = bounds.xmax - im.bounds.xmax bounds = galsim.BoundsI(ymin=bounds.ymin, ymax=bounds.ymax, xmin=bounds.xmin, xmax=im.bounds.xmax) if (bounds.ymin < im.bounds.ymin) or (bounds.ymax > im.bounds.ymax) or ( bounds.xmin < im.bounds.xmin) or (bounds.xmax > im.bounds.xmax): print 'Stamp bounds are not fully contained by the image bounds' return bounds, delta_x_min, delta_x_max, delta_y_min, delta_y_max
def test_bounds_centroid(): """Check that the input bounds are respected, and centroid coordinates make sense.""" # Make a simple object drawn into image with non-trivial bounds (even-sized). b = galsim.BoundsI(37, 326, 47, 336) test_scale = 0.15 test_sigma = 3.1 im = galsim.Image(bounds=b) im.scale = test_scale obj = galsim.Gaussian(sigma=test_sigma) obj.drawImage(image=im, scale=test_scale, method='no_pixel') mom = im.FindAdaptiveMom() np.testing.assert_almost_equal( mom.moments_centroid.x, im.trueCenter().x, decimal=7, err_msg='Moments x centroid differs from true center of even-sized image') np.testing.assert_almost_equal( mom.moments_centroid.y, im.trueCenter().y, decimal=7, err_msg='Moments y centroid differs from true center of even-sized image') # Draw the same object into odd-sized image with non-trivial bounds. b2 = galsim.BoundsI(b.xmin, b.xmax+1, b.ymin, b.ymax+1) im = galsim.Image(bounds=b2) im.scale = test_scale obj.drawImage(image=im, scale=test_scale, method='no_pixel') mom = im.FindAdaptiveMom() np.testing.assert_almost_equal( mom.moments_centroid.x, im.trueCenter().x, decimal=7, err_msg='Moments x centroid differs from true center of odd-sized image') np.testing.assert_almost_equal( mom.moments_centroid.y, im.trueCenter().y, decimal=7, err_msg='Moments y centroid differs from true center of odd-sized image') # Check that it still works with a symmetric sub-image. sub_im = im[galsim.BoundsI(b2.xmin+2, b2.xmax-2, b2.ymin+2, b2.ymax-2)] mom = sub_im.FindAdaptiveMom() np.testing.assert_almost_equal( mom.moments_centroid.x, sub_im.trueCenter().x, decimal=7, err_msg='Moments x centroid differs from true center of odd-sized subimage') np.testing.assert_almost_equal( mom.moments_centroid.y, sub_im.trueCenter().y, decimal=7, err_msg='Moments y centroid differs from true center of odd-sized subimage') # Check that we can take a weird/asymmetric sub-image, and it fails because of centroid shift. sub_im = im[galsim.BoundsI(b2.xmin, b2.xmax-100, b2.ymin+27, b2.ymax)] try: np.testing.assert_raises(RuntimeError, galsim.hsm.FindAdaptiveMom, sub_im) except ImportError: print('The assert_raises tests require nose') # ... and that it passes if we hand in a good centroid guess. Note that this test is a bit less # stringent than some of the previous ones, because our subimage cut off a decent part of the # light profile in the x direction, affecting the x centroid estimate. But the y centroid test # is the same precision as before. mom = sub_im.FindAdaptiveMom(guess_centroid=im.trueCenter()) np.testing.assert_approx_equal( mom.moments_centroid.x, im.trueCenter().x, significant=4, err_msg='Moments x centroid differs from true center of asymmetric subimage') np.testing.assert_almost_equal( mom.moments_centroid.y, im.trueCenter().y, decimal=7, err_msg='Moments y centroid differs from true center of asymmetric subimage')
def PSF(self, tt_dict, tt_stars): tt_field = self.get_TT_field(tt_dict) (self.x_tt, self.y_tt) = self.find_nearest_centroid(tt_stars) self.left_tt = int(self.x_tt - self.stampL) self.right_tt = int(self.x_tt + self.stampL) self.bottom_tt = int(self.y_tt - self.stampL) self.top_tt = int(self.y_tt + self.stampL) boundDifference = (self.right_tt - self.left_tt) - (self.top_tt - self.bottom_tt) if boundDifference == 0: b = galsim.BoundsI(self.left_tt, self.right_tt, self.bottom_tt, self.top_tt) if boundDifference == 1: b = galsim.BoundsI(self.left_tt, self.right_tt, self.bottom_tt, self.top_tt + 1) if boundDifference == -1: b = galsim.BoundsI(self.left_tt, self.right_tt + 1, self.bottom_tt, self.top_tt) print "Getting tt-field" s = time.time() tt_file = pyfits.open(tt_field) tt_data = tt_file[0].data tt_image = galsim.Image(tt_data) tt_file.close() print "Image imported. Time=", time.time() - s sub = tt_image.subImage(b) del tt_image return sub
def draw(self, profiles, image, method, offset, config, base, logger): """ Draw the profiles onto the stamp. """ if 'stamp_xsize' not in base or 'stamp_ysize' not in base: raise RuntimeError( "stamp size must be given for stamp type=BlendSet") nx = base['stamp_xsize'] ny = base['stamp_ysize'] wcs = base['wcs'] if profiles is not None: # Then we haven't drawn the full image yet. # We need to draw an image large enough to contain each of the cutouts bounds = galsim.BoundsI(galsim.PositionI(0, 0)) for pos in self.neighbor_pos: image_pos = wcs.toImage(pos) # Convert to nearest integer position image_pos = galsim.PositionI(int(image_pos.x + 0.5), int(image_pos.y + 0.5)) bounds += image_pos bounds = bounds.withBorder(max(nx, ny) // 2 + 1) self.full_images = [] for prof in profiles: im = galsim.ImageF(bounds=bounds, wcs=wcs) galsim.config.DrawBasic(prof, im, method, offset - im.true_center, config, base, logger) self.full_images.append(im) # Figure out what bounds to use for the cutouts. k = base['obj_num'] - self.first if k == 0: center_pos = galsim.PositionI(0, 0) else: center_pos = self.neighbor_pos[k - 1] center_image_pos = wcs.toImage(center_pos) xmin = int(center_image_pos.x) - nx // 2 + 1 ymin = int(center_image_pos.y) - ny // 2 + 1 self.bounds = galsim.BoundsI(xmin, xmin + nx - 1, ymin, ymin + ny - 1) # Add up the cutouts from the profile images image.setZero() image.wcs = wcs for full_im in self.full_images: assert full_im.bounds.includes(self.bounds) image += full_im[self.bounds] # And also build the neighbor image for the deblend image self.neighbor_image = image.copy() self.neighbor_image -= self.full_images[k][self.bounds] # Save this in base for the deblend output base['blend_neighbor_image'] = self.neighbor_image return image
def test_unweighted_moments(): sigma = 0.8 gal = galsim.Gaussian(sigma=sigma) scale = 0.02 # Use a small scale and a large image so we can neglect the impact of boundaries nx = ny = 1024 # and pixelization in tests. img1 = gal.drawImage(nx=nx, ny=ny, scale=scale, method='no_pixel') mom = galsim.utilities.unweighted_moments(img1) shape = galsim.utilities.unweighted_shape(mom) # Check that shape derived from moments is same as shape derived from image. shape2 = galsim.utilities.unweighted_shape(img1) assert shape == shape2 # Object should show up at the image true center. np.testing.assert_almost_equal(mom['Mx'], img1.trueCenter().x) np.testing.assert_almost_equal(mom['My'], img1.trueCenter().y) # And have the right sigma = rsqr/2 np.testing.assert_almost_equal(mom['Mxx']*scale**2, sigma**2) np.testing.assert_almost_equal(mom['Myy']*scale**2, sigma**2) np.testing.assert_almost_equal(mom['Mxy'], 0.0) np.testing.assert_almost_equal(shape['e1'], 0.0) np.testing.assert_almost_equal(shape['e2'], 0.0) # Add in some ellipticity and test that e1 = 0.2 e2 = 0.3 gal = gal.shear(e1=e1, e2=e2) img2 = gal.drawImage(nx=nx, ny=ny, scale=scale, method='no_pixel') mom2 = galsim.utilities.unweighted_moments(img2) shape3 = galsim.utilities.unweighted_shape(mom2) # Check that shape derived from moments is same as shape derived from image. shape4 = galsim.utilities.unweighted_shape(img2) assert shape3 == shape4 np.testing.assert_almost_equal(mom2['Mx'], img2.trueCenter().x) np.testing.assert_almost_equal(mom2['My'], img2.trueCenter().y) np.testing.assert_almost_equal(shape3['e1'], e1) np.testing.assert_almost_equal(shape3['e2'], e2) # Check subimage still works bds = galsim.BoundsI(15, 1022, 11, 1002) subimg = img2[bds] mom3 = galsim.utilities.unweighted_moments(subimg) shape5 = galsim.utilities.unweighted_shape(subimg) for key in mom2: np.testing.assert_almost_equal(mom2[key], mom3[key]) for key in shape3: np.testing.assert_almost_equal(shape3[key], shape5[key]) # Test unweighted_moments origin keyword. Using origin=trueCenter should make centroid result # (0.0, 0.0) mom4 = galsim.utilities.unweighted_moments(img2, origin=img2.trueCenter()) np.testing.assert_almost_equal(mom4['Mx'], 0.0) np.testing.assert_almost_equal(mom4['My'], 0.0)
def makeModels(data): # Make base images off which to model images = makeCube(data, data.forcedFilter) # Establish relevant model list and image bounds models = [] modelFluxList = [] bounds = galsim.BoundsI(1, int(data.imageSize), 1, int(data.imageSize)) for image in images: gal_moments = galsim.hsm.FindAdaptiveMom(image, strict=False) # If .FindAdaptiveMom was successful, make the model image if gal_moments.moments_status == 0: flux = gal_moments.moments_amp modelFluxList.append(flux) # Resize sigma based on pixel scale of the image sigma = gal_moments.moments_sigma * data.pixel_scale g1 = gal_moments.observed_shape.getG1() g2 = gal_moments.observed_shape.getG2() # Create new model using the Gaussian information above newModel = galsim.Gaussian(flux=flux, sigma=sigma) newModel = newModel.shear(g1=g1, g2=g2) model = galsim.Image(bounds, scale=data.pixel_scale) newModel.drawImage(image=model) model.addNoise(data.gaussian_noise) models.append(model) else: modelFluxList.append(None) data.modelFluxList = modelFluxList return models
def main(argv): # Try different interpolants! #interp1d = galsim.Linear(); #interp1d = galsim.Delta(); interp1d = galsim.Lanczos(5, conserve_dc=True, tol=1.e-4) #interp1d = galsim.Quintic(); interp2d = galsim.InterpolantXY(interp1d) try: inname = argv[1] outname = argv[2] dxOut = float(argv[3]) dim = int(argv[4]) nPhotons = int(argv[5]) g1 = float(argv[6]) if len(argv) > 6 else 0. g2 = float(argv[7]) if len(argv) > 7 else 0. except Exception as err: print __doc__ raise err galaxyImg = galsim.fits.read(inname) galaxy = galsim.InterpolatedImage(galaxyImg, x_interpolant=interp2d, dx=1.) galaxy.applyShear(g1=g1, g2=g2) rng = galsim.UniformDeviate(1534225) bounds = galsim.BoundsI(-dim / 2, dim / 2 + 1, -dim / 2, dim / 2 + 1) img = galsim.ImageF(bounds, scale=dxOut) galaxy.drawShoot(image=img, n_photons=nPhotons, rng=rng) img.write(outname)
def check_symm_noise(noise_image, msg): # A helper funciton to see if a noise image has 4-fold symmetric noise. im2 = noise_image.copy() # Clear out any wcs to make the test simpler im2.wcs = galsim.PixelScale(1.) noise = galsim.CorrelatedNoise(im2) cf = noise.drawImage(galsim.Image(bounds=galsim.BoundsI(-1,1,-1,1), scale=1)) # First check the variance print('variance: ',cf(0,0), noise.getVariance()) np.testing.assert_almost_equal(cf(0,0)/noise.getVariance(), 1.0, decimal=VAR_NDECIMAL, err_msg=msg + ':: noise variance is wrong.') cf_plus = np.array([ cf(1,0), cf(-1,0), cf(0,1), cf(0,-1) ]) cf_cross = np.array([ cf(1,1), cf(-1,-1), cf(-1,1), cf(1,-1) ]) print('plus pattern: ',cf_plus) print('diff relative to dc: ',(cf_plus-np.mean(cf_plus))/cf(0,0)) print('cross pattern: ',cf_cross) print('diff relative to dc: ',(cf_cross-np.mean(cf_cross))/cf(0,0)) # For now, don't make these asserts. Just print whether they will pass or fail. if True: if np.all(np.abs((cf_plus-np.mean(cf_plus))/cf(0,0)) < 0.01): print('plus test passes') else: print('*** FAIL ***') print(msg + ': plus pattern is not constant') if np.all(np.abs((cf_cross-np.mean(cf_cross))/cf(0,0)) < 0.01): print('cross test passes') else: print('*** FAIL ***') print(msg + ': cross pattern is not constant') else: np.testing.assert_almost_equal((cf_plus-np.mean(cf_plus))/cf(0,0), 0.0, decimal=2, err_msg=msg + ': plus pattern is not constant') np.testing.assert_almost_equal((cf_cross-np.mean(cf_cross))/cf(0,0), 0.0, decimal=2, err_msg=msg + ': cross pattern is not constant')
def SetupConfigImageSize(config, xsize, ysize, logger=None): """Do some further setup of the config dict at the image processing level based on the provided image size. - Set config['image_xsize'], config['image_ysize'] to the size of the image - Set config['image_origin'] to the origin of the image - Set config['image_center'] to the center of the image - Set config['image_bounds'] to the bounds of the image - Build the WCS based on either config['image']['wcs'] or config['image']['pixel_scale'] - Set config['wcs'] to be the built wcs - If wcs.isPixelScale(), also set config['pixel_scale'] for convenience. - Set config['world_center'] to either a given value or based on wcs and image_center Parameters: config: The configuration dict. xsize: The size of the image in the x-dimension. ysize: The size of the image in the y-dimension. logger: If given, a logger object to log progress. [default: None] """ logger = galsim.config.LoggerWrapper(logger) config['image_xsize'] = xsize config['image_ysize'] = ysize image = config['image'] origin = 1 # default if 'index_convention' in image: convention = galsim.config.ParseValue(image, 'index_convention', config, str)[0] if convention.lower() in ('0', 'c', 'python'): origin = 0 elif convention.lower() in ('1', 'fortran', 'fits'): origin = 1 else: raise galsim.GalSimConfigValueError( "Unknown index_convention", convention, ('0', 'c', 'python', '1', 'fortran', 'fits')) config['image_origin'] = galsim.PositionI(origin, origin) config['image_center'] = galsim.PositionD(origin + (xsize - 1.) / 2., origin + (ysize - 1.) / 2.) config['image_bounds'] = galsim.BoundsI(origin, origin + xsize - 1, origin, origin + ysize - 1) # Build the wcs wcs = galsim.config.BuildWCS(image, 'wcs', config, logger) config['wcs'] = wcs # If the WCS is a PixelScale or OffsetWCS, then store the pixel_scale in base. The # config apparatus does not use it -- we always use the wcs -- but we keep it in case # the user wants to use it for an Eval item. It's one of the variables they are allowed # to assume will be present for them. if wcs.isPixelScale(): config['pixel_scale'] = wcs.scale # Set world_center if 'world_center' in image: config['world_center'] = galsim.config.ParseValue( image, 'world_center', config, galsim.CelestialCoord)[0] else: config['world_center'] = wcs.toWorld(config['image_center'])
def __init__(self, real_kimage, imag_kimage, k_interpolant=None, stepk=None, gsparams=None): # make sure real_kimage, imag_kimage are really `Image`s, are floats, and are congruent. if not isinstance(real_kimage, galsim.Image) or not isinstance(imag_kimage, galsim.Image): raise ValueError("Supplied kimage is not an Image instance") if ((real_kimage.dtype != np.float32 and real_kimage.dtype != np.float64) or (imag_kimage.dtype != np.float32 and imag_kimage.dtype != np.float64)): raise ValueError("Supplied image does not have dtype of float32 or float64!") if real_kimage.bounds != imag_kimage.bounds: raise ValueError("Real and Imag kimages must have same bounds.") if real_kimage.scale != imag_kimage.scale: raise ValueError("Real and Imag kimages must have same scale.") # Make sure any `wcs`s are `PixelScale`s. if ((real_kimage.wcs is not None and not real_kimage.wcs.isPixelScale()) or (imag_kimage.wcs is not None and not imag_kimage.wcs.isPixelScale())): raise ValueError("Real and Imag kimage wcs's must be PixelScale's or None.") # Check for Hermitian symmetry properties of real_kimage and imag_kimage shape = real_kimage.array.shape # If image is even-sized, ignore first row/column since in this case not every pixel has # a symmetric partner to which to compare. bd = galsim.BoundsI(real_kimage.xmin + (1 if shape[1]%2==0 else 0), real_kimage.xmax, real_kimage.ymin + (1 if shape[0]%2==0 else 0), real_kimage.ymax) if not (np.allclose(real_kimage[bd].array, real_kimage[bd].array[::-1,::-1]) and np.allclose(imag_kimage[bd].array, -imag_kimage[bd].array[::-1,::-1])): raise ValueError("Real and Imag kimages must form a Hermitian complex matrix.") if stepk is None: stepk = real_kimage.scale else: if stepk < real_kimage.scale: import warnings warnings.warn( "Provided stepk is smaller than kimage.scale; overriding with kimage.scale.") stepk = real_kimage.scale self._real_kimage = real_kimage self._imag_kimage = imag_kimage self._stepk = stepk self._gsparams = gsparams # set up k_interpolant if none was provided by user, or check that the user-provided one # is of a valid type if k_interpolant is None: self.k_interpolant = galsim.Quintic(tol=1e-4) else: self.k_interpolant = galsim.utilities.convert_interpolant(k_interpolant) GSObject.__init__(self, galsim._galsim.SBInterpolatedKImage( self._real_kimage.image, self._imag_kimage.image, self._real_kimage.scale, self._stepk, self.k_interpolant, gsparams))
def __generateSubImages(self, row, column): # - 1 for border of 1 pixel between stamps b = galsim.BoundsI(column * self.width + 1, (column + 1) * self.width - 1, row * self.height + 1, (row + 1) * self.height - 1) subGalImage = self.galImage[b] subPSFImage = self.psfImage[b] return (subGalImage, subPSFImage)
def __init__(self, i_gal, stamp_size, gal_model, st_model, pointing, sca_center, real_wcs=False): self.i_gal = i_gal self.stamp_size = stamp_size self.gal_model = gal_model self.st_model = st_model self.pointing = pointing self.sca_center = sca_center self.real_wcs = real_wcs self.stamp_size_factor = old_div( int(self.gal_model.getGoodImageSize(wfirst.pixel_scale)), self.stamp_size) if self.stamp_size_factor == 0: self.stamp_size_factor = 1 self.wcs, self.sky_level = self.pointing.get_wcs() self.xy = self.wcs.toImage(self.sca_center) # galaxy position if self.real_wcs == True: self.xyI = galsim.PositionI(int(self.xy.x), int(self.xy.y)) self.b = galsim.BoundsI( xmin=self.xyI.x - old_div(int(self.stamp_size_factor * self.stamp_size), 2) + 1, ymin=self.xyI.y - old_div(int(self.stamp_size_factor * self.stamp_size), 2) + 1, xmax=self.xyI.x + old_div(int(self.stamp_size_factor * self.stamp_size), 2), ymax=self.xyI.y + old_div(int(self.stamp_size_factor * self.stamp_size), 2)) else: self.xyI = galsim.PositionI( int(self.stamp_size_factor * self.stamp_size), int(self.stamp_size_factor * self.stamp_size)) self.b = galsim.BoundsI(xmin=1, xmax=self.xyI.x, ymin=1, ymax=self.xyI.y)
def getStampBounds(self, ix, iy): """ Returns the bounding box for the stamp at tile coords (ix,iy). """ # these explicit casts are necessary in case ix,iy are numpy.ints ix = int(ix) iy = int(iy) self.checkCoords(ix, iy) ssize = self.stampSize return galsim.BoundsI(ix * ssize, (ix + 1) * ssize - 1, iy * ssize, (iy + 1) * ssize - 1)
def make_dm_wcs(galsim_wcs): """ convert galsim wcs to stack wcs Parameters ---------- galsim_wcs: galsim WCS Should be TAN or TAN-SIP Returns ------- DM Stack sky wcs """ if galsim_wcs.wcs_type == 'TAN': crpix = galsim_wcs.crpix # DM uses 0 offset, galsim uses FITS 1 offset stack_crpix = Point2D(crpix[0] - 1, crpix[1] - 1) cd_matrix = galsim_wcs.cd crval = geom.SpherePoint( galsim_wcs.center.ra / coord.radians, galsim_wcs.center.dec / coord.radians, geom.radians, ) stack_wcs = makeSkyWcs( crpix=stack_crpix, crval=crval, cdMatrix=cd_matrix, ) elif galsim_wcs.wcs_type == 'TAN-SIP': # No currently supported # this works with the 1-offset assumption from galsim # # this is not used if the lower bounds are 1, but the extra keywords # GS_{X,Y}MIN are set which we will remove below fake_bounds = galsim.BoundsI(1, 10, 1, 10) hdr = {} galsim_wcs.writeToFitsHeader(hdr, fake_bounds) del hdr["GS_XMIN"] del hdr["GS_YMIN"] metadata = PropertyList() for key, value in hdr.items(): metadata.set(key, value) stack_wcs = makeSkyWcs(metadata) return stack_wcs
def findSCA(wcs_dict, world_pos, include_border=False): """ This is a subroutine to take a dict of WCS (one per SCA) from galsim.wfirst.getWCS() and query which SCA a particular real-world coordinate would be located on. The position (`world_pos`) should be specified as a galsim.CelestialCoord. If the position is not located on any of the SCAs, the result will be None. Note that if `wcs_dict` does not include all SCAs in it, then it's possible the position might lie on one of the SCAs that was not included. Depending on what the user wants to do with the results, they may wish to use the `include_border` keyword. This keyword determines whether or not to include an additional border corresponding to half of the gaps between SCAs. For example, if a user is drawing a single image they may wish to only know whether a given position falls onto an SCA, and if so, which one (ignoring everything in the gaps). In contrast, a user who plans to make a sequence of dithered images might find it most useful to know whether the position is either on an SCA or close enough that in a small dither sequence it might appear on the SCA at some point. Use of `include_border` switches between these scenarios. @param wcs_dict The dict of WCS's output from galsim.wfirst.getWCS(). @param world_pos A galsim.CelestialCoord indicating the sky position of interest. @param include_border If True, then include the half-border around SCA to cover the gap between each sensor. [default: False] @returns an integer value of the SCA on which the position falls, or None if the position is not on any SCA. """ # Sanity check args. if not isinstance(wcs_dict, dict): raise TypeError( "wcs_dict should be a dict containing WCS output by galsim.wfirst.getWCS." ) if not isinstance(world_pos, galsim.CelestialCoord): raise TypeError( "Position on the sky must be given as a galsim.CelestialCoord.") # Set up the minimum and maximum pixel values, depending on whether or not to include the # border. We put it immediately into a galsim.BoundsI(), since the routine returns xmin, xmax, # ymin, ymax: xmin, xmax, ymin, ymax = _calculate_minmax_pix(include_border) bounds_list = [ galsim.BoundsI(x1, x2, y1, y2) for x1, x2, y1, y2 in zip(xmin, xmax, ymin, ymax) ] sca = None for i_sca in wcs_dict: wcs = wcs_dict[i_sca] image_pos = wcs.toImage(world_pos) if bounds_list[i_sca].includes(image_pos): sca = i_sca break return sca
def get_tt_subImages(centroid, tt_images, stamp_size=6.0): tt_subImages = [] for img in tt_images: x0 = centroid[0] y0 = centroid[1] r = centroid[2] L = stamp_size * r b = galsim.BoundsI(int(x0 - 0.5 * L), int(x0 + 0.5 * L), int(y0 - 0.5 * L), int(y0 + 0.5 * L)) sub = img.subImage(b) tt_subImages.append(sub) return tt_subImages
def postage_stamp(self, image_data=None): if not self.is_within_image(): raise ValueError("The postage stamp is outside the CCD boundary.") else: if image_data == None: f = pyfits.open(self.fname) image_data = f[0].data f.close() im = galsim.Image(image_data) boundDifference = (self.rightBound - self.leftBound) - ( self.topBound - self.bottomBound) if boundDifference == 0: b = galsim.BoundsI(self.leftBound, self.rightBound, self.bottomBound, self.topBound) if boundDifference == 1: b = galsim.BoundsI(self.leftBound, self.rightBound, self.bottomBound, self.topBound + 1) if boundDifference == -1: b = galsim.BoundsI(self.leftBound, self.rightBound + 1, self.bottomBound, self.topBound) stamp = im.subImage(b) return stamp
def main(): for profile, exactGal, nComponents, maxRadius in PROFILES: exactGal.applyShear(e1=E1, e2=E2) psf = galsim.Gaussian(sigma=PSF_SIGMA) exactObj = galsim.Convolve([exactGal, psf]) exactImage = exactObj.draw(dx=1.0) exactImage.write(profile + "-exact.fits") amplitudes, variances = lsst.shapelet.tractor.loadParameters( profile, nComponents, maxRadius) componentGals = [] for n, (amplitude, variance) in enumerate(zip(amplitudes, variances)): componentGal = galsim.Gaussian(flux=amplitude, sigma=GALAXY_RADIUS * variance**0.5) componentGal.applyShear(e1=E1, e2=E2) componentGals.append(componentGal) if MAKE_COMPONENT_IMAGES: componentObj = galsim.Convolve([componentGal, psf]) componentImage = galsim.ImageD(exactImage.bounds) componentObj.draw(componentImage, dx=1.0) componentImage.write("%s-approx-%0d.fits" % (profile, n)) approxGal = galsim.Add(componentGals) approxObj = galsim.Convolve([approxGal, psf]) approxImage = galsim.ImageD(exactImage.bounds) approxObj.draw(approxImage, dx=1.0) approxImage.write(profile + "-approx.fits") f1 = galsim.Add([ makeGaussian(flux=0.600000, e1=0.09090909, e2=0.36363636, sigma=2.25810086), makeGaussian(flux=0.400000, e1=-0.11111111, e2=-0.11111111, sigma=2.98130750), ]) f2 = galsim.Add([ makeGaussian(flux=0.350000, e1=-0.26315789, e2=-0.21052632, sigma=2.99069756), makeGaussian(flux=0.650000, e1=-0.12500000, e2=0.12500000, sigma=2.80606626), ]) f3 = galsim.Convolve([f1, f2]) image = galsim.ImageD(galsim.BoundsI(-20, 20, -20, 20)) f3.draw(image, dx=1.0) image.write("gaussians.fits")
def test_galsim_bounds_error(): """Test basic usage of GalSimBoundsError """ pos = galsim.PositionI(0,0) bounds = galsim.BoundsI(1,10,1,10) err = galsim.GalSimBoundsError("Test", pos, bounds) print('str = ',str(err)) print('repr = ',repr(err)) assert str(err) == "Test galsim.PositionI(0,0) not in galsim.BoundsI(1,10,1,10)" assert err.pos == pos assert err.bounds == bounds assert isinstance(err, galsim.GalSimError) assert isinstance(err, ValueError) do_pickle(err)
def setup(): """Build an input image and catalog used by a few tests below. """ wcs = galsim.TanWCS( galsim.AffineTransform(0.26, 0.05, -0.08, -0.24, galsim.PositionD(1024, 1024)), #galsim.AffineTransform(0.26, 0., 0., 0.26, galsim.PositionD(1024,1024)), galsim.CelestialCoord(5 * galsim.arcmin, -25 * galsim.degrees)) # Make the image (copied from test_single_image in test_simple.py) image = galsim.Image(2048, 2048, wcs=wcs) # Where to put the stars. x_list = [ 123.12, 345.98, 567.25, 1094.94, 924.15, 1532.74, 1743.11, 888.39, 1033.29, 1409.31 ] y_list = [ 345.43, 567.45, 1094.32, 924.29, 1532.92, 1743.83, 888.83, 1033.19, 1409.20, 123.11 ] # Draw a Gaussian PSF at each location on the image. sigma = 1.3 g1 = 0.23 g2 = -0.17 du = 0.09 # in arcsec dv = -0.07 flux = 123.45 psf = galsim.Gaussian(sigma=sigma).shear(g1=g1, g2=g2).shift(du, dv) * flux for x, y in zip(x_list, y_list): bounds = galsim.BoundsI(int(x - 31), int(x + 32), int(y - 31), int(y + 32)) offset = galsim.PositionD(x - int(x) - 0.5, y - int(y) - 0.5) psf.drawImage(image=image[bounds], method='no_pixel', offset=offset) image.addNoise( galsim.GaussianNoise(rng=galsim.BaseDeviate(1234), sigma=1e-6)) # Write out the image to a file image_file = os.path.join('output', 'test_stats_image.fits') image.write(image_file) # Write out the catalog to a file dtype = [('x', 'f8'), ('y', 'f8')] data = np.empty(len(x_list), dtype=dtype) data['x'] = x_list data['y'] = y_list cat_file = os.path.join('output', 'test_stats_cat.fits') fitsio.write(cat_file, data, clobber=True)
def calculate_bounds(obj, pos, image): """Calculate a good bounds to use for this object based on its position. Also return the offset to use when drawing onto the postage stamp. """ obj_on_image = image.wcs.toImage(obj, image_pos=pos) N = obj_on_image.getGoodImageSize(1.0) xmin = int(math.floor(pos.x) - N/2) xmax = int(math.ceil(pos.x) + N/2) ymin = int(math.floor(pos.y) - N/2) ymax = int(math.ceil(pos.y) + N/2) bounds = galsim.BoundsI(xmin, xmax, ymin, ymax) bounds = bounds & image.bounds offset = pos - bounds.true_center return bounds, offset
def test_dep_bounds(): """Test the deprecated methods in galsim/deprecated/bounds.py """ import time t1 = time.time() bi = galsim.BoundsI(123,345,234,567) bf = galsim.BoundsD(123.,345.,234.,567.) for b in [bi, bf]: check_dep(b.setXMin,101) np.testing.assert_almost_equal(b.xmin, 101) np.testing.assert_almost_equal(b.xmax, 345) np.testing.assert_almost_equal(b.ymin, 234) np.testing.assert_almost_equal(b.ymax, 567) check_dep(b.setXMax,401) np.testing.assert_almost_equal(b.xmin, 101) np.testing.assert_almost_equal(b.xmax, 401) np.testing.assert_almost_equal(b.ymin, 234) np.testing.assert_almost_equal(b.ymax, 567) check_dep(b.setYMin,201) np.testing.assert_almost_equal(b.xmin, 101) np.testing.assert_almost_equal(b.xmax, 401) np.testing.assert_almost_equal(b.ymin, 201) np.testing.assert_almost_equal(b.ymax, 567) check_dep(b.setYMax,501) np.testing.assert_almost_equal(b.xmin, 101) np.testing.assert_almost_equal(b.xmax, 401) np.testing.assert_almost_equal(b.ymin, 201) np.testing.assert_almost_equal(b.ymax, 501) b2 = check_dep(b.addBorder,2) np.testing.assert_almost_equal(b.xmin, 101) np.testing.assert_almost_equal(b.xmax, 401) np.testing.assert_almost_equal(b.ymin, 201) np.testing.assert_almost_equal(b.ymax, 501) np.testing.assert_almost_equal(b2.xmin, 99) np.testing.assert_almost_equal(b2.xmax, 403) np.testing.assert_almost_equal(b2.ymin, 199) np.testing.assert_almost_equal(b2.ymax, 503) t2 = time.time() print 'time for %s = %.2f'%(funcname(),t2-t1)
def SetupConfigImageSize(config, xsize, ysize): """Do some further setup of the config dict at the image processing level based on the provided image size. - Set config['image_xsize'], config['image_ysize'] to the size of the image - Set config['image_origin'] to the origin of the image - Set config['image_center'] to the center of the image - Set config['image_bounds'] to the bounds of the image - Build the WCS based on either config['image']['wcs'] or config['image']['pixel_scale'] - Set config['wcs'] to be the built wcs - If wcs.isPixelScale(), also set config['pixel_scale'] for convenience. @param config The configuration dict. @param xsize The size of the image in the x-dimension. @param ysize The size of the image in the y-dimension. """ config['image_xsize'] = xsize config['image_ysize'] = ysize origin = 1 # default if 'index_convention' in config['image']: convention = galsim.config.ParseValue(config['image'], 'index_convention', config, str)[0] if convention.lower() in ['0', 'c', 'python']: origin = 0 elif convention.lower() in ['1', 'fortran', 'fits']: origin = 1 else: raise AttributeError("Unknown index_convention: %s" % convention) config['image_origin'] = galsim.PositionI(origin, origin) config['image_center'] = galsim.PositionD(origin + (xsize - 1.) / 2., origin + (ysize - 1.) / 2.) config['image_bounds'] = galsim.BoundsI(origin, origin + xsize - 1, origin, origin + ysize - 1) # Build the wcs wcs = galsim.config.BuildWCS(config) config['wcs'] = wcs # If the WCS is a PixelScale or OffsetWCS, then store the pixel_scale in base. The # config apparatus does not use it -- we always use the wcs -- but we keep it in case # the user wants to use it for an Eval item. It's one of the variables they are allowed # to assume will be present for them. if wcs.isPixelScale(): config['pixel_scale'] = wcs.scale
def get_subImages(image_star_table, image, stamp_size=6.): subImages = [] table = asciidata.open(image_star_table) #out_table = asciidata.create(4,table.nrows) f = pyfits.open(image) image_data = f[1].data img = galsim.Image(image_data) for i in range(table.nrows): x0 = table[0][i] y0 = table[1][i] r = table[2][i] L = stamp_size * r b = galsim.BoundsI(fix(int(x0 - 0.5 * L)), fix(int(x0 + 0.5 * L)), fix(int(y0 - 0.5 * L)), fix(int(y0 + 0.5 * L))) sub = img.subImage(b) subImages.append(sub) return subImages
def process(self, cache, pend): Id = cache.Id inFname = os.path.join(cache.expDir, 'image-%d-%s.fits' % (Id, pend)) assert os.path.exists(inFname) gal_image = galsim.fits.read(inFname) psfFWHM = cache.expDir.split('_psf')[-1] psfFname = os.path.join(cache.expDir, 'psf-%s.fits' % (psfFWHM)) assert os.path.exists(psfFname) psf_img = galsim.fits.read(psfFname) # Basic parameters scale = 0.168 ngrid = 64 nx = 100 ny = 100 ngal = nx * ny # Get the shear information gList = np.array([-0.02, 0., 0.02]) gList = gList[[eval(i) for i in pend.split('-')[-1]]] self.log.info('Processing for %s' % pend) self.log.info('shear List is for %s' % gList) types = [('regauss_e1','>f8'), ('regauss_e2','>f8'),\ ('regauss_detR','>f8'), ('regauss_resolution','>f8'),\ ] data = [] for i in range(ngal): ix = i % nx iy = i // nx b = galsim.BoundsI(ix * ngrid, (ix + 1) * ngrid - 1, iy * ngrid, (iy + 1) * ngrid - 1) sub_img = gal_image[b] result = galsim.hsm.EstimateShear(sub_img, psf_img, strict=False) data.append((result.corrected_e1,result.corrected_e2,\ result.moments_sigma,result.resolution_factor)) del result, sub_img gc.collect() out = np.array(data, types) outFname = os.path.join(cache.expDir, 'hsm-%d-%s.fits' % (Id, pend)) fitsio.write(outFname, out) del data, out gc.collect() return
def render_stamp(self, gal_orig, g1, g2, theta, xshift, yshift, mu, mirror): # transform gal = gal_orig.copy() gal.applyDilation(self.args.size_rescale) gal.applyRotation(theta * galsim.radians) gal = gal if not mirror else gal.transform(-1.0, 0.0, 0.0, 1.0) gal.applyLensing(g1=g1, g2=g2, mu=mu) # convolve psf = galsim.Gaussian(fwhm=self.args.gaussian_psf_fwhm) pixel = galsim.Pixel(scale=self.args.pixel_scale) final = galsim.Convolve([psf, pixel, gal]) # render at subpixel translation offset = galsim.PositionD(xshift, yshift) bbox = galsim.BoundsI(0, self.args.stamp_full_sz - 1, 0, self.args.stamp_full_sz - 1) galaxy_image = galsim.ImageF(self.args.stamp_full_sz, self.args.stamp_full_sz, scale=self.args.pixel_scale) galaxy_image.setOrigin(0, 0) stamp = galaxy_image.subImage(bbox) final.draw(stamp, normalization='flux', scale=self.args.pixel_scale, offset=offset) # whiten current_var = -1.0 additional_var = self.args.noise_std**2 if self.args.noise_whiten: current_var = final.noise.whitenImage(stamp) additional_var = self.args.noise_std**2 - current_var if additional_var < 0.0 and self.args.noise_whiten_can_fail: # pre-whitening failed return None, None, None, None # add noise if additional_var > 0.0: new_noise = galsim.GaussianNoise(self.rng, sigma=additional_var**0.5) new_noise.applyTo(stamp) return stamp, gal, current_var, additional_var
def get_subImage(x0, y0, L, image, out_dir, out_name, save_img=False): f = pyfits.open(image) image_data = f[0].data f.close() img = galsim.Image(image_data) xmin = int(x0 - L / 2.) xmax = xmin + L ymin = int(y0 - L / 2.) ymax = ymin + L b = galsim.BoundsI(xmin, xmax, ymin, ymax) sub = img.subImage(b) if save_img: try: sub.write(out_dir + out_name + ".fits") except: subprocess.call(["mkdir", out_dir]) sub.write(out_dir + out_name + ".fits") return sub
def roman_psf_rotation(): b = galsim.BoundsI(1,32,1,32) WCS1 = wfirst.getWCS(world_pos = galsim.CelestialCoord(ra=100*galsim.degrees, dec=-10*galsim.degrees), PA = 0.*galsim.radians)[1] WCS2 = wfirst.getWCS(world_pos = galsim.CelestialCoord(ra=100*galsim.degrees, dec=-10*galsim.degrees), PA = 30.*galsim.radians)[1] psf1 = wfirst.getPSF(1, 'H158', wcs=WCS1, pupil_bin=4, wavelength=wfirst.getBandpasses(AB_zeropoint=True)['H158'].effective_wavelength) psf2 = wfirst.getPSF(1, 'H158', wcs=WCS2, pupil_bin=4, wavelength=wfirst.getBandpasses(AB_zeropoint=True)['H158'].effective_wavelength) #star_model1 = galsim.DeltaFunction(flux=1.) #star_model2 = galsim.DeltaFunction(flux=1.) star_stamp1 = galsim.Image(b, scale=wfirst.pixel_scale) star_stamp2 = galsim.Image(b, scale=wfirst.pixel_scale) #star_model1 = galsim.Convolve(star_model1, psf1) #star_model2 = galsim.Convolve(star_model2, psf2) psf1.drawImage(image=star_stamp1) psf2.drawImage(image=star_stamp2) np.savetxt("/hpc/group/cosmology/masaya/wfirst_simulation/paper/roman_psf_PA0b.txt", star_stamp1.array) np.savetxt("/hpc/group/cosmology/masaya/wfirst_simulation/paper/roman_psf_PA30b.txt", star_stamp2.array)
def get_stamp(image, x_pos, y_pos, stamp_size): "Get postage stamp to run im3shape on" "Expects galsim image, SExtractor X_IMAGE,Y_IMAGE and stamp size as input" "Returns stamp, x0 and y0 - coordinates of object in stamp (starting from 0)" half = stamp_size / 2. x_min, x_max, y_min, y_max = int(x_pos - half), int(x_pos + half), int(y_pos - half), int(y_pos + half) over_edge = (x_min < 0) | (y_min < 0) | (x_max > image.array.shape[1]) | ( y_max > image.array.shape[0]) if over_edge: logging.warning('galaxy stamp overlaps edge of image, skipping') return 1 subBounds = galsim.BoundsI(x_min, x_max - 1, y_min, y_max - 1) stamp = image[subBounds] #stamp = img_data[ypos-half:ypos+half, xpos-half:xpos+half] x0, y0 = x_pos - x_min, y_pos - y_min return stamp.array, x0, y0
def test_dep_bounds(): """Test the deprecated methods in galsim/deprecated/bounds.py """ bi = galsim.BoundsI(123, 345, 234, 567) bf = galsim.BoundsD(123., 345., 234., 567.) for b in [bi, bf]: check_dep(b.setXMin, 101) np.testing.assert_almost_equal(b.xmin, 101) np.testing.assert_almost_equal(b.xmax, 345) np.testing.assert_almost_equal(b.ymin, 234) np.testing.assert_almost_equal(b.ymax, 567) check_dep(b.setXMax, 401) np.testing.assert_almost_equal(b.xmin, 101) np.testing.assert_almost_equal(b.xmax, 401) np.testing.assert_almost_equal(b.ymin, 234) np.testing.assert_almost_equal(b.ymax, 567) check_dep(b.setYMin, 201) np.testing.assert_almost_equal(b.xmin, 101) np.testing.assert_almost_equal(b.xmax, 401) np.testing.assert_almost_equal(b.ymin, 201) np.testing.assert_almost_equal(b.ymax, 567) check_dep(b.setYMax, 501) np.testing.assert_almost_equal(b.xmin, 101) np.testing.assert_almost_equal(b.xmax, 401) np.testing.assert_almost_equal(b.ymin, 201) np.testing.assert_almost_equal(b.ymax, 501) b2 = check_dep(b.addBorder, 2) np.testing.assert_almost_equal(b.xmin, 101) np.testing.assert_almost_equal(b.xmax, 401) np.testing.assert_almost_equal(b.ymin, 201) np.testing.assert_almost_equal(b.ymax, 501) np.testing.assert_almost_equal(b2.xmin, 99) np.testing.assert_almost_equal(b2.xmax, 403) np.testing.assert_almost_equal(b2.ymin, 199) np.testing.assert_almost_equal(b2.ymax, 503)