Welcome to the documentation for odi-tools¶
odi-tools is a suite of tools written in Pyraf, Astropy, Scipy, and Numpy to process individual QuickReduced images into single stacked images using a set of “best practices” for ODI data.
In this documentation we will provide descriptions of how to obtain and run the software, as well as a brief tutorial on using QuickReduced images.
Getting started with odi-tools¶
Installation¶
To use this code simply fork this repository and clone it onto your local machine:
$ git clone https://github.com/bjanesh/odi-tools.git
$ cd odi-tools
Optionally add this folder to your $PATH
so the odi-scripts maybe
used in any current working directory.
To run the scripts you will need to install a number of dependencies:
$ pip install numpy scipy astropy photutils pyraf tqdm matplotlib pandas
It is possible to install these packages without root access by using the
--user
option:
$ pip install --user package-name
As noted on the astropy website, it might also be beneficial to use the --no-deps
option when installing astropy to stop pip
from automatically upgrading any
of your previously installed packages, such as numpy
:
$ pip install --no-deps astropy
QuickReduce, ODI-PPA, and odi-tools¶
QuickReduce is a set of pure python tools to reduce data from ODI. QuickReduce was created by Ralf Kotulla (UW Milwaukee, UW Madison) for the WIYN Observatory. The source code for QuickReduce is now on github. Documenation for the QuickReduce pipeline is available at this link.
The ODI-PPA is the online portal used to access, sort, and run QuickReduce on your ODI data. Information for gaining access and using the portal can be found at these help pages.
odi-tools is designed to work on images that have been processed using QuickReduce and downloaded from the ODI-PPA.
Running QuickReduce¶
After you become familiar with the layout and operation of the ODI-PPA, you can use these following steps to process your data. The options we list here are what we have determined to be the best practices for running QuickReduce. It is important to remember that these options can be data dependent. We will update these options should the change.
Add the images you wish to reduce to a collection in the ODI-PPA and from the collection action menu, choose QuickReduce. See the PPA help pages for information about creating collections.
Run QuickReduce with the following options. The
[X]
denotes that the option is selected.[X]
WCS[X]
Photometry[X]
Fringe (i- and z-band only)[X]
Persistency[X]
Nonlinearity[X]
Pupil Ghost (calibrations)[ ]
Pupil Ghost (science)[X]
Use Bad Pixel Masks[X]
Cosmic Ray Removal, 3 iteration(s)
You should give this job a meaningful name and check the
Email me when when finished
box.When you receive the email letting you know your job is complete, download the QuickReduce data to your hard drive using the
Download Results
button on the QuickReduce job page. You don’t need to select any of the optional boxes, just name the job and click submit. Eventually awget
command will pop up. Copy it to your clipboard, navigate to the folder you want the data to go into, then paste the wget command in your command line.At this point you are ready to start running
odi-tools
. See the Basic usage documentation for information on starting this process. See An Introduction to working with Quick Reduced Images for a brief tutorial on getting to know a QuickReduced image.
An Introduction to working with Quick Reduced Images¶
Basic usage¶
All you need to do to get started is download your QR-ed data from the ODI-PPA using the wget download command, then follow these steps. An explination of running quick reduce from ODI-PPA will be given in other sections of the documentation:
Preparing your data¶
- move all individual
.fz
files into the top level folder:mv calibrated/**/*.fz .
- unpack the compressed fits files using funpack
- you need to rename your files to match the appropriate dither
pointing identification. for example, QR files are named by the pattern
OBSID_OBJECT_FILTER.JOBID.fits
. The final digit of the OBSID e.g.20151008T195949.1
needs to match the number sequence of the dithers 1-9. Your data may not match this pattern due to restarted observations, multiple night observations, etc.
Running the code (a broad overview)¶
- copy
example_config.yaml
to your data directory asconfig.yaml
and edit the file to match your preferences/data. Make sure that the number for each image matches the correct number in the dither sequence! - run
odi_process.py
in the folder containing the unpacked/renamed fits images. This will (optionally) illumination correct the images, fix their WCS, reproject them to a common pixel scale, and perform background subtraction on them. - this will take a while, so make sure nothing bad happened
- run
odi_scalestack_process.py
in the folder containing the unpacked/renamed fits images. This will detect bright stellar sources in the images and use them to calculate a scaling factor relative to the image in the sequence with the lowest airmass, then apply the scale, stack the images, then add in a common background value. - finished! check your images to make sure everything went okay.
Example configuration file¶
Here are the contents of example_config.yaml
available on the odi-tools
GitHub repo
# odi-tools configuration file
basic:
object: M13 # the name of your object
filters: [odi_g, odi_r, odi_i] # correct filter strings required
instrument: 5odi # podi | 5odi | mosaic; script will
# verify using image header info
processing: # optional steps performed in odi_process.py
illumination_correction: yes # if yes, set dark sky flat source below
dark_sky_flat_source: object # object | master
wcs_correction: yes
reproject: yes
scale_images: yes
stack_images: yes
# list the images you want to process
# be sure to associate the filename with the correct dither pointing!
# OBSID and image header are NOT always an accurate reflection of the absolute dither position
# so you must use your notes / observing log to define them here
# sections must be named according to the filter names
odi_g:
1: 20130510T002928.1_m13-9_odi_g.5869.fits
2: 20130510T002928.2_m13-9_odi_g.5869.fits
3: 20130510T002928.3_m13-9_odi_g.5869.fits
4: 20130510T002928.4_m13-9_odi_g.5869.fits
5: 20130510T002928.5_m13-9_odi_g.5869.fits
6: 20130510T002928.6_m13-9_odi_g.5869.fits
7: 20130510T002928.7_m13-9_odi_g.5869.fits
8: 20130510T002928.8_m13-9_odi_g.5869.fits
9: 20130510T002928.9_m13-9_odi_g.5869.fits
odi_r:
1: 20130510T002928.1_m13-9_odi_r.5869.fits
2: 20130510T002928.2_m13-9_odi_r.5869.fits
3: 20130510T002928.3_m13-9_odi_r.5869.fits
4: 20130510T002928.4_m13-9_odi_r.5869.fits
5: 20130510T002928.5_m13-9_odi_r.5869.fits
6: 20130510T002928.6_m13-9_odi_r.5869.fits
7: 20130510T002928.7_m13-9_odi_r.5869.fits
8: 20130510T002928.8_m13-9_odi_r.5869.fits
9: 20130510T002928.9_m13-9_odi_r.5869.fits
odi_i:
1: 20130510T002928.1_m13-9_odi_i.5869.fits
2: 20130510T002928.2_m13-9_odi_i.5869.fits
3: 20130510T002928.3_m13-9_odi_i.5869.fits
4: 20130510T002928.4_m13-9_odi_i.5869.fits
5: 20130510T002928.5_m13-9_odi_i.5869.fits
6: 20130510T002928.6_m13-9_odi_i.5869.fits
7: 20130510T002928.7_m13-9_odi_i.5869.fits
8: 20130510T002928.8_m13-9_odi_i.5869.fits
9: 20130510T002928.9_m13-9_odi_i.5869.fits
Individual modules and tasks¶
Modules¶
Python configuration to run odi-tools¶
The function odi_config.py
imports all of the modules needed to run
odi-tools
as well as sets up the needed dictionaries and directories.
It is imported in the following way in the main odi-tool
scripts
(odi_process
, odi_scalestack_process
, odi_phot_process
).
>>> import odi_config as odi
Once it is imported, the dictionaries are directories created in
odi_config.py
can be referenced throughout the odi-tools
pipeline in
the following manner
>>> example_dict = odi.dictionary
>>> example_directory = odi.directory
Similarly, we can also reference all of the modules and functions imported
in odi_config.py
.
>>> gaps = odi.get_gaps(img, ota)
The OTA dictionaries¶
There are two dictionaries defined by this function that correspond to different versions of ODI.
podi_dictionary
odi5_dictionary
As an example, here are the contents of podi_dictionary
:
podi_dictionary = {1: 'OTA33.SCI',
2: 'OTA34.SCI',
3: 'OTA44.SCI',
4: 'OTA43.SCI',
5: 'OTA42.SCI',
6: 'OTA32.SCI',
7: 'OTA22.SCI',
8: 'OTA23.SCI',
9: 'OTA24.SCI'
}
For those that are not familiar with Python, a dictionary is made up of pairs
of keys
and values
. The keys
are to the left of the colon, and the
values
are to the right. In our case, the keys
are the numbers 1-9, and
the values are the names of the different OTAs, (e.g. OTA33.SCI
). The
dictionaries provide a clean way to work through a multi-extension fits image
like those produced by ODI. The simpled code example below provides an
illustration of how this is done in odi-tools
.
>>> images = ['img1.fits','img2.fits']
>>> for img in images:
>>> for key in podi_dictionary:
>>> print img, key
This would produce the following output:
'img1.fits' 'OTA33.SCI'
'img1.fits' 'OTA34.SCI'
'img1.fits' 'OTA44.SCI'
'img1.fits' 'OTA43.SCI'
'img1.fits' 'OTA42.SCI'
'img1.fits' 'OTA32.SCI'
'img1.fits' 'OTA22.SCI'
'img1.fits' 'OTA23.SCI'
'img1.fits' 'OTA24.SCI'
'img2.fits' 'OTA33.SCI'
'img2.fits' 'OTA34.SCI'
'img2.fits' 'OTA44.SCI'
'img2.fits' 'OTA43.SCI'
'img2.fits' 'OTA42.SCI'
'img2.fits' 'OTA32.SCI'
'img2.fits' 'OTA22.SCI'
'img2.fits' 'OTA23.SCI'
'img2.fits' 'OTA24.SCI'
Although this is a simple example it illustrates the overall workflow of
odi-tools
.
The odi5_dictionary
works the same way, but simply has more OTAs. The
correct dictionary is selected by odi_helpers.instrument()
. If the
instrument used was 5odi
, odi5_dictionary
is used for odi-tools
,
if it was podi
, podi_dictionary
is used.
Processing directories¶
odi_config.py
also sets up a number of directories to hold the
intermediate data products during the data processing. Here is an example
of how one of those directories is created
>>> bpmdirectory = 'bpmasks'
>>> if not os.path.exists(bpmdirectory):
>>> print 'Creating directory for bad pixel masks...'
>>> os.makedirs(bpmdirectory)
>>> bppath = bpmdirectory+'/'
The directory in this case is given the name bpmasks
. Then, we check if
the directory already exists. If is does not, the directory is created. Once
this directory is created it can be accessed by other odi-tools
modules
and scripts using the following
>>> odi.bppath
Here is a full list of the directories created
bpmasks
- directory for bad pixel masksillcor
- directory for illumination corrected ota imagesreproj
- directory for reprojected ota imagesbgsub
- directory for background subtracted ota imagesscaled
- directory for scaled ota imagesotastack
- directory for stacked ota imagesskyflat
- directory for sky flatscoords
- directory for coordinate filesmatch
- directory for match filessdssoffline
- directory for sdss catalogstwomassoffline
- directory for 2mass catalogsgaiaoffline
- directory for gaia catalogssources
- directory for detected sources
Reading configuration files¶
ODI helper functions¶
These are simple functions used throughout the odi-tools
pipeline.
Calculating background statistics¶
Source catalogs¶
These functions retrieve and parse the SDSS and Gaia DR1 catalogs to be used when fixing the WCS solutions of individual OTAs.
Measuring Stellar FWHM¶
There are a number of steps in odi-tools
that require having a measurement
of the stellar fwhm of sources on individual OTAs or on a fully stacked image.
In order to get these measurements we use the pyraf
task rimexam
on
a list of known x and y positions for SDSS sources on a given field.
Here is how the parameters are set for rimexam
:
iraf.tv.rimexam.setParam('radius',radius)
iraf.tv.rimexam.setParam('buffer',buff)
iraf.tv.rimexam.setParam('width',width)
iraf.tv.rimexam.setParam('rplot',20.)
iraf.tv.rimexam.setParam('center','yes')
iraf.tv.rimexam.setParam('fittype','gaussian')
iraf.tv.rimexam.setParam('iterati',1)
Creating an OTA bad pixel mask¶
Create OTA gaps bad pixel masks¶
Improving WCS solutions¶
These are the functions that improve the WCS solutions of otas based on source catalogs with known Ra and Dec positions.
Find sources for OTA scaling¶
These functions locate the bright sources on OTAs, runs phot on these sources, and calculate the scaling factor needed to be applied to each OTA based on a reference image.