All italic text here have been taken from Stetson's manual.
The only input file for this procedure is a FITS file containing reference frame image. Here we use sample FITS form astwro package (NGC6871 I filter 20s frame). Below we get filepath for this image, as well as create instances of Daophot
and Allstar
classes - wrappers around daophot
and allstar
respectively.
One should also provide daophot.opt
, photo.opt
and allstar.opt
in apropiriete constructors. Here default, build in, sample, opt
files are used.
In [1]:
from astwro.sampledata import fits_image
frame = fits_image()
Daophot
object creates temporary working directory (runner directory), which is passed to Allstar
constructor to share.
In [2]:
from astwro.pydaophot import Daophot, Allstar
dp = Daophot(image=frame)
al = Allstar(dir=dp.dir)
Daophot got FITS file in construction, which will be automatically ATTACHed.
Daophot FIND
parameters Number of frames averaged, summed
are defaulted to 1,1
, below are provided for clarity.
In [3]:
res = dp.FInd(frames_av=1, frames_sum=1)
Check some results returned by FIND
, every method for daophot
command returns results object.
In [4]:
print ("{} pixels analysed, sky estimate {}, {} stars found.".format(res.pixels, res.sky, res.stars))
In [ ]:
Also, take a look into runner directory
In [5]:
!ls -lt $dp.dir
We see symlinks to input image and opt
files, and i.coo
- result of FIND
Below we run photometry, providing explicitly radius of aperture A1
and IS
, OS
sky radiuses.
In [6]:
res = dp.PHotometry(apertures=[8], IS=35, OS=50)
List of stars generated by daophot commands, can be easily get as astwro.starlist.Starlist
being essentially pandas.DataFrame
:
In [7]:
stars = res.photometry_starlist
Let's check 10 stars with least A1 error (mag_err
column). (pandas style)
In [8]:
stars.sort_values('mag_err').iloc[:10]
Out[8]:
SORT
command of daophor
is not implemented (yet) in pydaohot
. But we do sorting by ourself.
In [9]:
sorted_stars = stars.sort_values('mag')
sorted_stars.renumber()
Here we write sorted list back info photometry file at default name (overwriting existing one), because it's convenient to use default files in next commands.
In [10]:
dp.write_starlist(sorted_stars, 'i.ap')
Out[10]:
In [11]:
!head -n20 $dp.PHotometry_result.photometry_file
In [12]:
dp.PHotometry_result.photometry_file
Out[12]:
In [13]:
pick_res = dp.PIck(faintest_mag=20, number_of_stars_to_pick=40)
If no error reported, symlink to image file (renamed to i.fits
), and all daophot output files (i.*
) are in the working directory of runner:
In [14]:
ls $dp.dir
One may examine and improve i.lst
list of PSF stars. Or use astwro.tools.gapick.py
to obtain list of PSF stars optimised by genetic algorithm.
tell it the name of your complete (sorted renumbered) aperture photometry file, the name of the file with the list of PSF stars, and the name of the disk file you want the point spread function stored in (the default should be fine) [...]
If the frame is crowded it is probably worth your while to generate the first PSF with the "VARIABLE PSF" option set to -1 --- pure analytic PSF. That way, the companions will not generate ghosts in the model PSF that will come back to haunt you later. You should also have specified a reasonably generous fitting radius --- these stars have been preselected to be as isolated as possible and you want the best fits you can get. But remember to avoid letting neighbor stars intrude within one fitting radius of the center of any PSF star.
For illustration we will set VARIABLE PSF
option, before PSf()
In [15]:
dp.set_options('VARIABLE PSF', 2)
psf_res = dp.PSf()
We use allstar
. (GROUP
and NSTAR
command are not implemented in current version of pydaophot
). We use prepared above Allstar
object: al
operating on the same runner dir that dp
.
As parameter we set input image (we haven't do that on constructor), and nei
file produced by PSf()
. We do not remember name i.psf
so use psf_res.nei_file
property.
Finally we order allstar
to produce subtracted FITS .
In [16]:
alls_res = al.ALlstar(image_file=frame, stars=psf_res.nei_file, subtracted_image_file='is.fits')
All result
objects, has get_buffer()
method, useful to lookup unparsed daophot
or allstar
output:
In [17]:
print (alls_res.get_buffer())
Examine each of the PSF stars and its environs. Have all of the PSF stars subtracted out more or less cleanly, or should some of them be rejected from further use as PSF stars? (If so use a text editor to delete these stars from the LST file.) Have the neighbors mostly disappeared, or have they left behind big zits? Have you uncovered any faint companions that FIND missed?[...]
The absolute path to subtracted file (like for most output files) is available as result's property:
In [18]:
sub_img = alls_res.subtracted_image_file
We can also generate region file for psf stars:
In [19]:
from astwro.starlist.ds9 import write_ds9_regions
reg_file_path = dp.file_from_runner_dir('lst.reg')
write_ds9_regions(pick_res.picked_starlist, reg_file_path)
In [20]:
# One can run ds9 directly from notebook:
!ds9 $sub_img -regions $reg_file_path
Lookup into runner dir:
In [21]:
ls $al.dir
In [22]:
sub_res = dp.SUbstar(subtract=alls_res.profile_photometry_file, leave_in=pick_res.picked_stars_file)
You have now created a new picture which has the PSF stars still in it but from which the known neighbors of these PSF stars have been mostly removed
In [23]:
for i in range(3):
print ("Iteration {}: Allstar chi: {}".format(i, alls_res.als_stars.chi.mean()))
dp.image = 'is.fits'
respsf = dp.PSf()
print ("Iteration {}: PSF chi: {}".format(i, respsf.chi))
alls_res = al.ALlstar(image_file=frame, stars='i.nei')
dp.image = frame
dp.SUbstar(subtract='i.als', leave_in='i.lst')
print ("Final: Allstar chi: {}".format(alls_res.als_stars.chi.mean()))
In [37]:
alls_res.als_stars
Out[37]:
Check last image with subtracted PSF stars neighbours.
In [24]:
!ds9 $dp.SUbstar_result.subtracted_image_file -regions $reg_file_path
Once you have produced a frame in which the PSF stars and their neighbors all subtract out cleanly, one more time through PSF should produce a point-spread function you can be proud of.
In [25]:
dp.image = 'is.fits'
psf_res = dp.PSf()
print ("PSF file: {}".format(psf_res.psf_file))
In [ ]: