astropy:docs

Source code for delphinus.delphinus

#!/usr/bin/env python
# encoding: utf-8
"""
Interface to dolphot [1]_ and related code for reading DOLPHOT outputs.

Note that the documentation here may be copied verbatim from Andrew Dolphin's
documentation where appropriate (e.g. for defining parameters).

.. [1] DOLPHOT. http://americano.dolphinsim.com/dolphot/
"""

import os
import shutil
import time
import subprocess

from phottable import DolphotTable


[docs]class Dolphot(object): """The :class:`Dolphot` class manages a single run of `dolphot` itself. This class manages `dolphot` parameters, runs `dolphot`, and provides paths to the `dolphot` output, including the ability to compile the `dolphot` photometry tables into a Pythonic data structure. Parameters ---------- workDir : str Work directory for photometry **params : kwargs Parameters general to a run of Dolphot. Image-specific parameters are passed with the :meth:`add_image` and :meth:`add_reference` methods. Attributes ---------- images : list List of dictionaries for images being photometered. Has fields for parameters, etc, associated with each photometered image referenceImage : dict Parameter info for reference image. Has fields `path` and `params`. Set to None if no reference image is being used params : dict General parameters (those not specific to images) workDir : str Work directory for photometry outputName : str Base name of the output files. Created when calling :meth:`run`. apcorPath : str Path to the aperture correction data file columnsPath : str Path to the columns definition file infoPath : str Path to the info file psfsPath : str Path to the psfs file tablePath : str Path to the HDF5 table, if it it create. `None` otherwise. """ def __init__(self, workDir, **params): self.images = [] self.referenceImage = None self.params = params if os.path.exists(workDir) is False: os.makedirs(workDir) self.workDir = workDir self.execTime = None self.tablePath = None
[docs] def add_image(self, imagePath, key=None, band=None, **params): """Add an image to the set to be photometered. Parameters ---------- imagePath : str Full path to the FITS file to be photomered. MEF or single extension fits are valid. key : str String that uniquely identifies an image in your pipeline. The key is used in the HDF5 photometry table to show the order of images. Set to the file name, without directory and extension if left as None. band : str Band-pass of this image. Can be used to help create cursory CMDs. If not set, the bandpass of each image is labeled `'None'`. **params : kwargs Parameters to be passed for this image. See parameter listing of :meth:`DolphotParameters.setup_image`. """ if key is None: key = os.path.splitext(os.path.basename(imagePath))[0] if band is None: band = 'None' self.images.append({"path": imagePath, "image_key": key, "params": params, "band": band})
[docs] def add_reference(self, imagePath, **params): """Add an image to the set to be photometered. Parameters ---------- imagePath : str Full path to the FITS file to be photomered. MEF or single extension fits are valid. **params : dict Parameters to be passed for this image. See parameter listing of :meth:`DolphotParameters.setup_image`. """ self.referenceImage = {"path": imagePath, "params": params}
[docs] def change_param(self, key, param): """Change or add a single parameter. These must be general parameters. """ self.params[key] = param
[docs] def write_parameters(self, outputName, fullPath=False): """Write parameters to a .params file for DOLPHOT. This method is automatically called by :meth:`run`. """ dolphotParams = DolphotParameters(**self.params) for doc in self.images: path = doc['path'] imParams = doc['params'] dolphotParams.setup_image(path, ref=False, **imParams) if self.referenceImage is not None: refPath = self.referenceImage['path'] refParams = self.referenceImage['params'] dolphotParams.setup_image(refPath, ref=True, **refParams) if not fullPath: self.paramPath = os.path.join(self.workDir, outputName + ".params") else: self.paramPath = outputName dolphotParams.write_parameters(self.paramPath)
[docs] def run(self, outputName, clean=True): """Run dolphot photometry given the parameter settings.""" outputPath = os.path.join(self.workDir, outputName) self.write_parameters(outputName) command = "dolphot %s -p%s" % (outputPath, self.paramPath) with Timer() as t: subprocess.call(command, shell=True) self.execTime = t.interval # Define paths to dolphot outputs self.outputName = outputName self._define_output_paths(self.outputName)
[docs] def run_ast(self, outputName, starListName): """Run dolphot photometry in artificial star test mode. This method differs from :meth:`run` in that it will create a directory to perform the AST in, so that multiple star lists can be simultaneously run on a single input photometry. That is, this method prevents the AST output of one star list from clobbering that of another. .. note:: This method may be deprecated. """ astDir = os.path.join(self.workDir, "%s_%s" % (outputName, starListName)) if not os.path.exists(astDir): os.makedirs(astDir) self._define_output_paths(outputName) # Symlink outputs into astDir _apcorPath = os.path.join(astDir, outputName + ".apcor") _columnsPath = os.path.join(astDir, outputName + ".columns") _infoPath = os.path.join(astDir, outputName + ".info") _psfsPath = os.path.join(astDir, outputName + ".psfs") _fakePath = os.path.join(astDir, outputName + ".fake") _photPath = os.path.join(astDir, outputName) os.symlink(self.apcorPath, _apcorPath) os.symlink(self.infoPath, _infoPath) os.symlink(self.columnsPath, _columnsPath) os.symlink(self.psfsPath, _psfsPath) os.symlink(self.photPath, _photPath) # Run photometry self.write_parameters(os.path.join(astDir, outputName + ".params"), fullPath=True) outputPath = os.path.join(astDir, outputName) command = "dolphot %s -p%s" % (outputPath, self.paramPath) with Timer() as t: subprocess.call(command, shell=True) self.execTime = t.interval # Move AST result back to main directory, labeled with star list name self.fakePath = os.path.join(self.workDir, "%s_%s.fake" % (outputName, starListName)) if os.path.exists(self.fakePath): os.remove(self.fakePath) shutil.move(_fakePath, self.fakePath) # Delete AST dir shutil.rmtree(astDir)
def _define_output_paths(self, outputName): """Define paths to the dolphot outputs""" self.apcorPath = os.path.join(self.workDir, outputName + ".apcor") self.columnsPath = os.path.join(self.workDir, outputName + ".columns") self.infoPath = os.path.join(self.workDir, outputName + ".info") self.psfsPath = os.path.join(self.workDir, outputName + ".psfs") self.fakePath = os.path.join(self.workDir, outputName + ".fake") self.warnPath = os.path.join(self.workDir, outputName + ".warnings") self.photPath = os.path.join(self.workDir, outputName) # path list for psf fits files self.psf_fits_paths = [os.path.join(self.workDir, outputName + ".%i.psf.fits" % n) for n in xrange(1, len(self.images) + 1)] # path list for resdiaul fits files self.res_fits_paths = [os.path.join(self.workDir, outputName + ".%i.res.fits" % n) for n in xrange(1, len(self.images) + 1)] self.outputName = outputName
[docs] def label_fake_output(self, label): """Renames artificial star test output (useful it running multiple fake star lists on the same photometry).""" newPath = os.path.join(self.workDir, "%s_%s.fake" % (self.outputName, label)) if newPath == self.fakePath: return if os.path.exists(newPath): os.remove(newPath) print self.fakePath, newPath shutil.move(self.fakePath, newPath) self.fakePath = newPath
[docs] def compile_hdf5(self, tablePath=None): """Make an HDF5 file of the photometric output.""" if tablePath is None: tablePath = os.path.join(self.workDir, self.outputName + ".h5") dolphotTable = DolphotTable.make(tablePath, self.images, self.referenceImage, self.photPath, self.psfsPath, self.apcorPath, execTime=self.execTime) self.tablePath = tablePath return dolphotTable
[docs]class DolphotParameters(object): """Handles parameters for Dolphot. General parameters are initialzed upon instantiation, while parameters for individual images are specified in the setup_image command. Parameters ---------- PSFPhot : int Type of photometry to be run. Options are - 0 (aperture), - 1 (standard PSF-fit) - 2 (PSF-fit weighted for central pixels). Option 1 is suggested for most photometric needs, but option 0 can provide superior photometry if the signal-to- noise is high and the field is uncrowded. FitSky : int Sky-fitting setting. Options are - 0 (use the sky map from calcsky) - 1 (fit the sky normally prior to each photometry measurement) - 2 (fit the sky inside the PSF region but outside the photometry aperture), - 3 (fit the sky within the photometry aperture as a 2-parameter PSF fit), and - 4 (fit the sky within the photometry aperture as a 4-parameter PSF fit). Options 1 and 3 are the suggested settings. Option 0 should be used only if the field is very uncrowded; option 2 can be used in extremely crowded fields; option 4 can help in fields with strong background gradients (though I have yet to see this be useful). RCentroid : int The centroid used for obtaining initial positions of stars is a square of size 2RCentroid + 1 on each side. SigFind : real Sigma detection threshold. Stars above this limit will be kept in the photometry until the final output. SigFindMult : real Multiple for sigma detection threshold in initial finding algorithm. This should be close to one for larger PSFs, and as low as 0.75 for badly undersampled PSFs. SigFinal : real Sigma threshold for a star to be listed in the final photometry list. To get all stars, set SigFinal equal to SigFind. MaxIT : int Maximum number of photometry iterations. FSPS : str The functional form of the analytic PSF. Allowable options are “Gauss” (Gaussian), “Lorentz” (Lorentzian), “Lorentz2” (a squared Lorentzian), and “G+L” (sum of Gaussian and Lorentzian). SkipSky : int Sampling of sky annulus; set to a number higher than 1 to gain speed at the expense of precision. This is only used if FitSky is set to 1. In general, this should never be larger than the FWHM of the PSF. SkySig : real Sigma rejection threshold for sky fit; only used if FitSky is set to 1. NoiseMult : real To allow for imperfect PSFs, the noise is increased by this value times the star brightness in the pixel when computing chi values. FSat : real Fraction of nominal saturation for which pixesl are considered saturated. Zero : real Zero point for a star of brightness 1 DN per second. PosStep : real Typical stepsize in x and y during photometry iterations. Should be set to a factor of a few smaller than the PSF FHWM. dPosMax : real Maximum position change of a star during a single photometry iteration. Note that this parameter is currently ignored. RCombine : real Minimum separation of two stars (they will be combined if they become closer than this value). This value can generally be about 2/3 of the PSF FWHM, but no less than 1.42. sigPSF : real Minimum signal-to-noise for a PSF solution to be attempted on a star. Fainter detections are assigned type 2. PSFStep : real Typical stepsize of FWHM during photometry iterations. Setting to zero will replace PSF solution with three-state solution in which a star will be very small, fit the stellar PSF, or very large. MinS : real Minimum FWHM for a good star (type 1). This should be set to something like half the PSF FWHM. MaxS : real Maximum FWHM for a good star (type 1). This needs to be set to something larger than the FWHM of the PSF. MaxE : real Maximum ellipticity for a good star (type 1). UseWCS : int Use WCS header information for alignment? Allowed values are 0 (no), 1 (use to estimate shift, scale, and rotation), or 2 (use to estimate a full distortion solution). Note that any shifts or rotations selected by img shift and img xform are applied in addition to what is determined by the WCS solution. If reducing HST data, selecting UseWCS=1 can eliminate the need for running the fitdistort utilities. UseWCS=2 generally is not recommended for HST data since the distortion coefficients provided with DOLPHOT provide higher-order corrections than do the WCS headers. Align : int Align images to reference? Allowed values are 0 (no), 1 (x/y offsets only), 2 (x/y offsets plus scale difference), and 3 (x/y offsets plus distortion). Rotate : int Correct for rotation in alignment? Allowed values are 0 (no) and 1 (yes). SecondPass : int Number of additional passes when finding stars to locate stars in the wings of brighter stars. Must be a non-negative value. SearchMode : int Sets the minimization used to determine star positions. Allowed values are 0 (chi divided by SNR) and 1 (chi only). A value of one appear safe for all applications. A value of zero has been seen to fail if images of very different exposure times are used together. Force1 : int Force all objects to be of class 1 or 2? Allowed values are 0 (no) and 1 (yes). For crowded stellar fields, this should be set to 1 and the chiand sharpness values used to discard extended objects. EPSF : int Allow elliptical PSFs in parameter fits? Allowed values are 0 (no) and 1 (yes). PSFsol : int Make analytic PSF solution? Allowed values are -1 (no), 0 (constant PSF), 1 (linear PSF variation), and 2 (quadratic PSF variation). PSFres : int Solve for PSF residual image? Allowed values are 0 (no) and 1 (yes). Turning this feature off can create nonlinearities in the photometry unless PSFphot is also set to zero. psfstars : str or None Specify coordinates of PSF stars. The file must contain extension, chip, X, and Y (the first four columns of DOLPHOT output). psfoff : real Coordinate offset of PSF star list. Values equal the list coordinates minus the DOLPHOT coordinates, and would thus be 0.5 if using a DAOPHOT or IRAF star list. ApCor : int Make aperture corrections? Allowed values are 0 (no) and 1 (yes). Default aperture corrections always have the potential for error, so it is strongly recommended that you manually examine the raw output from this process. SubPixel : int The number of PSF calculations made per dimension per pixel. For Nyquist-sampled images, this can be set to 1, but very small PSFs require the extra precision. FakeStars : str or None Run DOLPHOT in artificial star mode. The FakeStars parameter is the name of the text file containing the artificial star data. The file should contain the following information for each star, one star per line: extension (0 = main image), chip (usually 1), X, Y, and the number of counts on each image. If the warmstart option is being used, one also needs to specify the recovered X, Y, and object type values before the counts. Note that photometry must be run first; the photometry list, PSFs, etc. from DOLPHOT are used as inputs in the fake star routine. FakeMatch : real Maximum allowable distance between input and recovered artificial star. FakePSF : real Approximate FWHM of the image, used to determine which of two input stars a recovered star should be matched with. FakeStarPSF : int Use PSF residual from initial photometry run. This should be left at zero, unless the PSF residuals are small and well-measured. RandomFake : int Apply Poisson noise to fake stars when adding them. This should always be used, unless running fake star tests twice (once with and once without) to quantify photometric errors from crowding and background independently of the errors due to photon noise. xytfile : str or None star list filename for warmstart xytpsf : str or None PSF solution for the reference image for difference image photomtry. photsec : list or None Optinally, specify a subset fo the image to be photometered (relative to first image, or referene image). Pass a list of six integer values: extension (usually 0), Z (usually 1), minimum X, minimum Y, maximum X, maximum Y. """ def __init__(self, PSFPhot=2, FitSky=1, SkipSky=1, SkySig=2.25, SigFind=2.5, SigFindMult=0.85, SigFinal=3.0, MaxIT=25, NoiseMult=0.25, FSat=0.999, Zero=25.0, RCentroid=3, PosStep=0.6, dPosMax=3.0, RCombine=1.75, FPSF="G+L", sigPSF=10, PSFStep=0.25, MinS=1.0, MaxS=9.0, MaxE=0.5, UseWCS=0, Align=3, Rotate=1, secondPass=1, SearchMode=1, Force1=0, EPSF=1, PSFsol=0, PSFres=1, psfstars=None, psfoff=0.0, ApCor=0, SubPixel=1, FakeStars=None, FakeMatch=3., FakeStarPSF=0, FakePSF=1.5, RandomFake=1, xytfile=None, xytpsf=None, photsec=None): self.refImageParams = None self.imageParams = [] self.params = {"PSFPhot": PSFPhot, "FitSky": FitSky, "SkipSky": SkipSky, "SkySig": SkySig, "SigFind": SigFind, "SigFindMult": SigFindMult, "SigFinal": SigFinal, "MaxIT": MaxIT, "NoiseMult": NoiseMult, "FSat": FSat, "Zero": Zero, "RCentroid": RCentroid, "PosStep": PosStep, "dPosMax": dPosMax, "RCombine": RCombine, "FPSF": FPSF, "sigPSF": sigPSF, "PSFStep": PSFStep, "MinS": MinS, "MaxS": MaxS, "MaxE": MaxE, "UseWCS": UseWCS, "Align": Align, "Rotate": Rotate, "secondPass": secondPass, "SearchMode": SearchMode, "Force1": Force1, "EPSF": EPSF, "PSFsol": PSFsol, "PSFres": PSFres, "psfstars": psfstars, "psfoff": psfoff, "ApCor": ApCor, "SubPixel": SubPixel, "FakeStars": FakeStars, "FakeMatch": FakeMatch, "FakeStarPSF": FakeStarPSF, "FakePSF": FakePSF, "RandomFake": RandomFake, "xytfile": xytfile, "xytpsf": xytpsf, "photsec": photsec}
[docs] def setup_image(self, path, psfA=(3, 0, 0, 0, 0, 0), psfB=(3, 0, 0, 0, 0, 0), psfC=(0, 0, 0, 0, 0, 0), shift=(0, 0), xform=(1, 0, 0), aprad=20, apsky=(30, 50), RAper=2.5, RSky=(4.0, 10.0), RChi=None, RPSF=15, ref=False): """Configure the fitting parameters for a single image. This may also be the reference image if `ref=True` is set. Parameters ---------- path : str file path of FITS file (without the .fits suffix) psfA : tuple PSF XX term, length 6. Set the PSF x-FWHM and linear and quadratic variations. This value can be an initial guess that is later adjusted by DOLPHOT. psfB : tuple PSF YY term, length 6. Set the PSF y-FWHM and linear and quadratic variations. This value can be an initial guess that is later adjusted by DOLPHOT. psfC : tuple PSF XY term, length 6. Set the PSF eccentricity and linear and quadratic variations. This value can be an initial guess that is later adjusted by DOLPHOT. shift : tuple x,y shifts relative to reference. Set offset of image relative to reference. This value can be an initial guess that is later adjusted by DOLPHOT. Values are x and y on the image minus x and y on the reference image. Note that this parameter should not be set for the reference image. xform : tuple Set the scale ratio, cubic distortion, and rotation of the image relative to the reference image. This value can be an initial guess that is later ad- justed by DOLPHOT. Note that this parameter should not be set for the reference image. aprad : real Radius for aperture correction apsky : tuple Set the inner and outer radii of the annulus used for calculating sky values for aperture corrections. raper : real Sets the size of the aperture within which photometry will be performed. For FitSky=0 or 1, this should include most of the light of the star. For FitSky=2, 3, or 4 options, this should also include significant “sky” area outside the star. rsky : tuple Inner, outer radius for computing sky values, if FitSky=1 is being used. This should be outside the bulk of the light from the star. Outer radius should be sufficiently large to compute an accurate sky. rpsf : int Size of the PSF used for star subtraction. The rule of thumb is to make sure this is sufficiently large that significant unsubtracted star light is not seen beyond the subtracted regions in the residual image. rchi : real Sets the size of the aperture within which the chi value will be calculated. This is used to determine object locations. This should generally include only the peak of the stellar PSF. RChi cannot be larger than RAper. If not defined, RChi is set equal to RAper. ref : bool set as True if this is the reference image, False otherwise """ # Chop off the .fits extension if necessary if path.endswith(".fits"): path = os.path.splitext(path)[0] imageDoc = {"file": path, "psfa": psfA, "psfb": psfB, "psfc": psfC, "shift": shift, "xform": xform, "aprad": aprad, "apsky": apsky, "RSky": RSky, "RAper": RAper, "RChi": RChi, "RPSF": RPSF, } if ref == True: self.refImageParams = imageDoc else: self.imageParams.append(imageDoc)
[docs] def write_parameters(self, path): """Write the parameter file to `path`.""" # pathDir = os.path.dirname(path) # if os.path.exists(pathDir) is False: os.makedirs(path) if os.path.exists(path) is True: os.remove(path) paramLines = [] paramLines.append("Nimg = %i" % len(self.imageParams)) if self.refImageParams is not None: paramLines += self._write_image_params(self.refImageParams, 0) for i, imageParam in enumerate(self.imageParams): paramLines += self._write_image_params(imageParam, i + 1) paramLines += self._write_general_params() paramTxt = "\n".join(paramLines) + "\n" f = open(path, 'w') f.write(paramTxt) f.close()
def _write_image_params(self, params, n): """Produces a list of strings, giving parameters for photometry of a given image (or reference) Parameters ---------- d : dict Dictionary of parameters for the image n : int Number of the image. Reference image is 0. """ prefix = "img%i_" % n formatters = {"file": "%s", "psfa": "%.2f %.2f %.2f %.2f %.2f %.2f", "psfb": "%.2f %.2f %.2f %.2f %.2f %.2f", "psfc": "%.2f %.2f %.2f %.2f %.2f %.2f", "shift": "%.2f %.2f", "xform": "%.2f %.2f %.2f", "aprad": "%.2f", "apsky": "%.2f %.2f", "RSky": "%.2f %.2f", "RAper": "%.2f", "RChi": "%.2f", "RPSF": "%i"} lines = [] for key, p in params.iteritems(): if p is None: continue if n == 0 and key in ['shift', 'xform']: continue if key not in formatters: continue # don't know this key if type(p) is list: p = tuple(p) lines.append(prefix + key + " = " + formatters[key] % p) return lines def _write_general_params(self): """Produces a list of strings for the general parameters not associated with specific images.""" formatters = {"PSFPhot": "%i", "FitSky": "%i", "SkipSky": "%.2f", "SkySig": "%.2f", "SigFind": "%.2f", "SigFindMult": "%.2f", "SigFinal": "%.2f", "MaxIT": "%i", "NoiseMult": "%.2f", "FSat": "%.2f", "Zero": "%.2f", "RCentroid": "%i", "PosStep": "%.2f", "dPosMax": "%.2f", "RCombine": "%.2f", "FPSF": "%s", "sigPSF": "%.2f", "PSFStep": "%.2f", "MinS": "%.2f", "MaxS": "%.2f", "MaxE": "%.2f", "UseWCS": "%i", "Align": "%i", "Rotate": "%i", "secondPass": "%i", "SearchMode": "%i", "Force1": "%i", "EPSF": "%i", "PSFsol": "%i", "PSFres": "%i", "psfstars": "%s", "psfoff": "%.1f", "ApCor": "%i", "SubPixel": "%i", "FakeStars": "%s", "FakeMatch": "%.2f", "FakeStarPSF": "%i", "FakePSF": "%.2f", "RandomFake": "%i", "xytfile": "%s", "xytpsf": "%s", "photsec": "%i %i %i %i %i %i"} lines = [] for key, p in self.params.iteritems(): if p is None: continue if key not in formatters: continue # don't know this key if type(p) is list: p = tuple(p) if key == "photsec": print key, p lines.append(key + " = " + formatters[key] % p) return lines
class Timer: """Timer function, via http://preshing.com/ 20110924/timing-your-code-using-pythons-with-statement This timer uses :func:`time.time` to measure wall time so that it can accurately measure the time taken by subprocesses (such as `dolphot`). """ def __enter__(self): self.start = time.time() return self def __exit__(self, *args): self.end = time.time() self.interval = self.end - self.start """ 1. Extension (zero for base image) 2. Chip (for three-dimensional FITS image) 3. Object X position on reference image (or first image, if no reference) 4. Object Y position on reference image (or first image, if no reference) 5. Chi for fit 6. Signal-to-noise 7. Object sharpness 8. Object roundness 9. Direction of major axis (if not round) 10. Crowding 11. Object type (1=bright star, 2=faint, 3=elongated, 4=hot pixel, 5=extended) 12. Measured counts, image 1 13. Measured sky level, image 1 14. Normalized count rate, image 1 15. Normalized count rate uncertainty, image 1 16. Instrumental magnitude, image 1 17. Magnitude uncertainty, image 1 18. Chi, image 1 19. Signal-to-noise, image 1 20. Sharpness, image 1 21. Roundness, image 1 22. Crowding, image 1 23. PSF FWHM, image 1 24. PSF eccentricity, image 1 25. PSF a parameter, image 1 26. PSF b parameter, image 1 27. PSF c parameter, image 1 28. Photometry quality flag, image 1 29. Measured counts, image 2 30. Measured sky level, image 2 31. Normalized count rate, image 2 32. Normalized count rate uncertainty, image 2 33. Instrumental magnitude, image 2 34. Magnitude uncertainty, image 2 35. Chi, image 2 36. Signal-to-noise, image 2 37. Sharpness, image 2 38. Roundness, image 2 39. Crowding, image 2 40. PSF FWHM, image 2 41. PSF eccentricity, image 2 42. PSF a parameter, image 2 43. PSF b parameter, image 2 44. PSF c parameter, image 2 45. Photometry quality flag, image 2 """

Page Contents