def load_psfex(model_path: str, x: float, y: float): """ Since PSFEx generates a model using basis vectors, with the linear combination dependent on image position, this is used to collapse that into a useable kernel for convolution and insertion purposes. See https://psfex.readthedocs.io/en/latest/Appendices.html This function will return the PSFEx output to the pixel scale of the original image. To keep an oversampled PSF model image, use load_psfex_oversampled() :param model_path: Path to PSFEx-generated model, as a FITS file (usually ends in .psf) :param x: pixel x-coordinate to use for model input :param y: pixel y-coordinate to use for model input :return: numpy.ndarray representing the PSF model as an image. """ psfex_model = pex.PSFEx(model_path) xs = check_iterable(x) ys = check_iterable(y) psfs = [] for i, x in enumerate(xs): y = ys[i] psf = psfex_model.get_rec(y, x) centre_psf_x, centre_psf_y = psfex_model.get_center(y, x) centre_x, centre_y = psf.shape[1] / 2, psf.shape[0] / 2 psf = shift(psf, (centre_x - centre_psf_y, centre_y - centre_psf_x)) psfs.append(psf) return psfs
def __init__(self, psfex_file: str, data_shape: tuple, flux: float, x_0: float, y_0: float): self.psfex_file = psfex_file self.psfex_model = pex.PSFEx(psfex_file) self.data_shape = data_shape super().__init__(flux, x_0, y_0)
def make_psf_models(self): """ Start by making reference star file for later psfcat matching This arrangement is special to DECam data of a single cluster, where all images will have roughly the same center """ hdr = fits.getheader(self.image_files[0]) coord = astropy.coordinates.SkyCoord(hdr['CRVAL1'], hdr['CRVAL2'], unit='deg') result = Gaia.cone_search_async(coord, radius=1.2 * u.degree) catalog = result.get_data() catalog_wg = catalog[catalog['parallax'] >= catalog['parallax_error']] """ now do actual PSF modelling """ self.psfEx_models = [] for i, imagefile in enumerate(self.image_files): weightfile = self.weight_files[i] psfex_model_file = self._make_psf_model(imagefile, weightfile=weightfile, star_reference=catalog_wg) # move checkimages to psfex_output cmd = ' '.join(['mv chi* resi* samp* snap* proto*', self.psf_path]) os.system(cmd) try: self.psfEx_models.append(psfex.PSFEx(psfex_model_file)) except: pdb.set_trace()
def _set_psfex_objects(self, image_info): import psfex self.psfex_objects = [] for psfex_file in image_info['psfex_path']: print('loading:', psfex_file) p = psfex.PSFEx(psfex_file) self.psfex_objects.append(p)
def psfex_extract(psfex_file, row, col): """Extract PSF image from PSFex result.""" try: import psfex except ImportError: raise Exception("Need to install PSFex library first!") return psfex.PSFEx(psfex_file).get_rec(row, col)
def _load_psfex(self, meds_filename, psfex_name=None): """ load the psfex object from the file """ import psfex if psfex_name is None: psfex_name = get_psfex_name(meds_filename) logger.info('loading psfex: %s' % psfex_name) self.psfex = psfex.PSFEx(psfex_name)
def run_meds_only(self, outfile="superbit.meds", catalog='coadd_catalog.fits', source_selection=True): # Make a MEDS, clobbering if needed # Set up the paths to the psf and temporary data self.set_working_path() self.set_psf_path() print("I enter run_meds_only") # Image info needs a catalog, a list of images, a list of psfs try: self.psfEx_models pass except: self.psfEx_models = [] for i, image in enumerate(self.image_files): psf_name = self.psf_path + '/' + ( image.split('/')[-1]).split('.fits')[0] + '_cat.psf' self.psfEx_models.append(psfex.PSFEx(psf_name)) try: self.catalog pass except: try: le_cat = fits.open(catalog) #self.catalog = le_cat[2].data self.catalog = le_cat[1].data if source_selection is True: self.select_sources_from_catalog(fullcat=le_cat) except: print("coadd catalog could not be loaded; check name?") pdb.set_trace() # Make the image_info struct. image_info = self.make_image_info_struct() # Make the object_info struct. obj_info = self.make_object_info_struct() # Make the MEDS config file. meds_config = self.make_meds_config() # Create metadata for MEDS meta = self._meds_metadata(magzp=30.0) # Finally, make and write the MEDS file. medsObj = meds.maker.MEDSMaker(obj_info, image_info, config=meds_config, psf_data=self.psfEx_models, meta_data=meta) medsObj.write(outfile)
def make_psf_models(self,gaia_select=False): self.psfEx_models = [] for imagefile in self.image_files: #update as necessary weightfile=self.mask_file psfex_model_file = self._make_psf_model(imagefile,weightfile = weightfile,gaia_select=gaia_select) # move checkimages to psfex_output cmd = ' '.join(['mv chi* resi* samp* snap* proto*',self.psf_path]) os.system(cmd) try: self.psfEx_models.append(psfex.PSFEx(psfex_model_file)) except: pdb.set_trace()
def _load_psfs(self, psf_files): """ load the psfs """ import psfex self.psf_list = [] for i, psf_file in enumerate(psf_files): if isinstance(psf_file, str): logger.info('loading psfex file %s' % psf_file) p = psfex.PSFEx(psf_file) else: if i == 0: logger.info('got non-string psf input, assuming ' 'are psfs with correct interface') p = psf_file self.psf_list.append(p)
def produce(self, posX, posY): print "CreatePSFFile input %s \n" % self.infile if not os.path.isfile(self.infile): print " CreatePSFFile input file %s do not exists \n" % self.infile return # outpath = os.path.normpath(self.outfile) if os.path.exists(outpath): os.remove(outpath) self.posX = posX self.posY = posY # fitsfile = os.path.normpath(self.posX,self.posY) pex = psfex.PSFEx(self.infile) image = pex.get_rec(self.posX, self.posY) # print "writing PSF image to file %s \n" % self.outfile self.writePSF(image)
def _get_psfex_objects(self, meds): """ Load psfex objects for all images, including coadd """ import psfex psfex_list = [] info = meds.get_image_info() nimage = info.size for i in xrange(nimage): impath = info['image_path'][i] psf_ext = self._psfex_ext_from_image_path(info, impath) pex = psfex.PSFEx( meds._fits, ext=psf_ext, ) psfex_list.append(pex) return psfex_list
def build(psffile, x, y, stampsize, psfexworked=True): #print 'psffile' #raw_input() try: a = psfex.PSFEx(psffile) im = a.get_rec(y, x)[3:-4, 3:-4] im /= np.sum(im.ravel()) except: print "dump_psfex -inFile_psf %s -xpix %s -ypix %s -gridSize %s" % ( psffile, x, y, stampsize) psf = os.popen( "dump_psfex -inFile_psf %s -xpix %s -ypix %s -gridSize %s" % (psffile, x, y, stampsize)).readlines() ix, iy, psfval = [], [], [] for line in psf: # print line line = line.replace('\n', '') if line.startswith('PSF:'): linelist = line.split() ix += [int(linelist[1])] iy += [int(linelist[2])] psfval += [float(linelist[5])] elif line.startswith("IMAGE_CENTER"): linelist = line.split() IMAGE_CENTERX = float(linelist[1]) IMAGE_CENTERY = float(linelist[2]) ix, iy, psfval = np.array(ix), np.array(iy), np.array(psfval) im = np.zeros((stampsize, stampsize)) for x, y, p in zip(ix, iy, psfval): im[y, x] = p return im, (round(x), round(y))
def measure_psf_shapes_erin(xlist, ylist, psf_file_name, file_name): """Given x,y positions, a psf solution file, and the wcs, measure shapes and sizes of the PSF model. We use the HSM module from GalSim to do this. Also, this uses Erin's psfex module to render the images rather than the GalSim module. Returns e1, e2, size, flag. """ import psfex print 'Read in PSFEx file: ', psf_file_name n_psf = len(xlist) e1_list = [999.] * n_psf e2_list = [999.] * n_psf s_list = [999.] * n_psf flag_list = [0] * n_psf try: psf = psfex.PSFEx(psf_file_name) except Exception as e: print 'Caught ', e flag_list = [PSFEX_FAILURE] * n_psf return e1_list, e2_list, s_list, flag_list if psf._psfex is None: # Erin doesn't throw an exception for errors. # The _psfex attribute just ends up as None, so check for that. print 'psf._psfex is None' flag_list = [PSFEX_FAILURE] * n_psf return e1_list, e2_list, s_list, flag_list wcs = galsim.fits.read(file_name).wcs for i in range(n_psf): x = xlist[i] y = ylist[i] print 'Measure PSFEx model shape at ', x, y, ' with Erin\'s code.' # Note that this code renders the image in the original coordinate system, # rather than in RA/Dec oriented coordinates. So we'll need to correct for that. im_ar = psf.get_rec(y, x) local_wcs = wcs.jacobian(galsim.PositionD(x, y)) #print 'local wcs = ',local_wcs #print 'pixel scale = ',numpy.sqrt(local_wcs.pixelArea()) #print 'psf center = ',psf.get_center(y,x) pixel_scale = numpy.sqrt(local_wcs.pixelArea()) im = galsim.Image(array=im_ar, scale=pixel_scale) try: shape_data = im.FindAdaptiveMom(strict=False) except: print ' *** Bad measurement (caught exception). Mask this one.' flag_list[i] = PSFEX_BAD_MEASUREMENT continue if shape_data.moments_status != 0: print 'status = ', shape_data.moments_status print ' *** Bad measurement. Mask this one.' flag_list[i] = PSFEX_BAD_MEASUREMENT continue cen = psf.get_center(y, x) true_center = galsim.PositionD(cen[1] + 1, cen[0] + 1) dx = shape_data.moments_centroid.x - true_center.x dy = shape_data.moments_centroid.y - true_center.y #print 'centroid = ',shape_data.moments_centroid #print 'trueCenter = ',true_center #print 'dcentroid = ',dx,dy # Use at least 0.5 here. max_centroid_shift = max(MAX_CENTROID_SHIFT, 0.5) if dx**2 + dy**2 > max_centroid_shift**2: print ' *** Centroid shifted by ', dx, dy, '. Mask this one.' flag_list[i] = PSFEX_CENTROID_SHIFT continue #print 'shape = ',shape_data.observed_shape #print 'sigma = ',shape_data.moments_sigma * pixel_scale g1, g2, s = apply_wcs(local_wcs, shape_data.observed_shape.g1, shape_data.observed_shape.g2, shape_data.moments_sigma) #print 'after wcs: ',g1,g2,s e1_list[i] = g1 e2_list[i] = g2 s_list[i] = s return e1_list, e2_list, s_list, flag_list