Photometric Calibration

This notebook demonstrates how to perform photometric calibration using reference catalogs to convert instrumental magnitudes to standard magnitudes.

1. Load Data

Use DataBrowser to query and filter synced data for photometric analysis.

Filter data for:

  • Target: T00528

  • Filter: r-band

  • Pattern: *100.fits (100-second exposures)

[1]:
from ezphot.utils import DataBrowser
databrowser = DataBrowser('scidata')
databrowser.objname = 'T00528'
databrowser.filter = 'm600'
target_imgset = databrowser.search('*100.fits', 'science')
target_imglist = target_imgset.target_images
[INFO] Found 90 files matching '/home/hhchoi1022/ezphot/data/scidata/*/*/T00528/*/m600/*100.fits'
Loading Science Images: 100%|██████████| 90/90 [00:00<00:00, 95.45it/s]
[2]:
target_img = target_imglist[0]
target_img.show('coord')
[2]:
(<Figure size 800x600 with 2 Axes>,
 <WCSAxes: title={'center': 'calib_7DT14_T00528_20250906_025855_m600_100.fits'}>)
../_images/example_photometriccalibration_4_1.png

2. Photometric Calibration

Convert instrumental magnitudes to standard magnitudes using reference catalogs. A photometric catalog is required - see the Aperture Photometry example.

2.1. Load Source Catalog

[3]:
from ezphot.methods import AperturePhotometry
target_catalog = target_img.catalog # You can access to the catalog after running aperture photometry with save = True

aperturephot = AperturePhotometry()
aperturephot.sex_photometry(
    target_img = target_img,
    target_bkg = target_img.bkgmap,
    target_bkgrms = target_img.bkgrms,
    target_mask = None,
    detection_sigma = 5,
    aperture_dismater_arcsec = [5, 7, 10],
    aperture_dismater_seeing = [3.5, 4.5],
    kron_factor = 2.5,
    save = True, # To load the catalog as attribute of target_img instance, save = True is required.
    verbose = True,
    visualize = True,
    save_fig = False,
)
Saved: /home/hhchoi1022/ezphot/data/scidata/7DT/7DT_C361K_HIGH_1x1/T00528/7DT14/m600/subbkg_calib_7DT14_T00528_20250906_025855_m600_100.fits
../_images/example_photometriccalibration_7_1.png
Start SExtractor process...=====================
RUN COMMAND: source-extractor /home/hhchoi1022/ezphot/data/scidata/7DT/7DT_C361K_HIGH_1x1/T00528/7DT14/m600/subbkg_calib_7DT14_T00528_20250906_025855_m600_100.fits -c /home/hhchoi1022/ezphot/config/common/sextractor/7DT_C361K_HIGH_1x1.sexconfig -BACK_TYPE MANUAL -SEEING_FWHM 3.19 -PIXEL_SCALE 0.5064013569110675 -PHOT_APERTURES 9.90,13.86,19.80,22.14,28.46 -SATUR_LEVEL 59596.19854736328 -PHOT_AUTOPARAMS 2.5,3.5 -CATALOG_NAME /home/hhchoi1022/ezphot/data/scidata/7DT/7DT_C361K_HIGH_1x1/T00528/7DT14/m600/calib_7DT14_T00528_20250906_025855_m600_100.fits.cat -WEIGHT_GAIN N -WEIGHT_IMAGE /home/hhchoi1022/ezphot/data/scidata/7DT/7DT_C361K_HIGH_1x1/T00528/7DT14/m600/calib_7DT14_T00528_20250906_025855_m600_100.fits.bkgrms -WEIGHT_TYPE MAP_RMS
SExtractor process finished=====================
Output path: /home/hhchoi1022/ezphot/data/scidata/7DT/7DT_C361K_HIGH_1x1/T00528/7DT14/m600/calib_7DT14_T00528_20250906_025855_m600_100.fits.cat
Saved: /home/hhchoi1022/ezphot/data/scidata/7DT/7DT_C361K_HIGH_1x1/T00528/7DT14/m600/calib_7DT14_T00528_20250906_025855_m600_100.fits.cat
../_images/example_photometriccalibration_7_3.png
[REMOVE] /home/hhchoi1022/ezphot/data/scidata/7DT/7DT_C361K_HIGH_1x1/T00528/7DT14/m600/subbkg_calib_7DT14_T00528_20250906_025855_m600_100.fits
[REMOVE] /home/hhchoi1022/ezphot/data/scidata/7DT/7DT_C361K_HIGH_1x1/T00528/7DT14/m600/subbkg_calib_7DT14_T00528_20250906_025855_m600_100.fits.status
[REMOVE] /home/hhchoi1022/ezphot/data/scidata/7DT/7DT_C361K_HIGH_1x1/T00528/7DT14/m600/subbkg_calib_7DT14_T00528_20250906_025855_m600_100.fits.info
[3]:
Catalog( N_selected/N_sources = None/2440, is_exists=True, catalog_type=all, path=/home/hhchoi1022/ezphot/data/scidata/7DT/7DT_C361K_HIGH_1x1/T00528/7DT14/m600/calib_7DT14_T00528_20250906_025855_m600_100.fits.cat)

2.2. Run Calibration

Use PhotometricCalibration to calibrate your catalog and update the image headers.

Process:

  1. Load reference catalog from archive

  2. Match reference sources to target catalog

  3. Select isolated point sources using quality criteria

  4. Calculate zero points for each aperture

  5. Update catalog and image headers

Updated Headers:

  • SEEING, SKYSIG, ZP_* (zero points)

Updated Columns:

  • MAG_APERMAGSKY_APER

  • MAG_APER_1MAGSKY_APER_1

  • etc.

[4]:
from ezphot.methods import PhotometricCalibration
photcal = PhotometricCalibration()
photcal.help()
Help for PhotometricCalibration

Public methods:
- apply_color_terms(target_img: Union[ezphot.imageobjects.scienceimage.ScienceImage, ezphot.imageobjects.referenceimage.ReferenceImage], target_catalog: ezphot.dataobjects.catalog.Catalog, comparison_catalog: ezphot.dataobjects.catalog.Catalog, max_distance_second: float = 1.0, save: bool = True, verbose: bool = False)
- apply_mag_terms(target_img: Union[ezphot.imageobjects.scienceimage.ScienceImage, ezphot.imageobjects.referenceimage.ReferenceImage], target_catalog: ezphot.dataobjects.catalog.Catalog, save: bool = True, verbose: bool = False)
- apply_zp(target_img: Union[ezphot.imageobjects.scienceimage.ScienceImage, ezphot.imageobjects.referenceimage.ReferenceImage], target_catalog: ezphot.dataobjects.catalog.Catalog, save: bool = True, verbose: bool = True)
- determine_reference_mag_range(target_catalog: ezphot.dataobjects.catalog.Catalog, bin_width=0.5, sigma_clip=5, magnitude_key='MAG_AUTO', zp_key='ZP_AUTO', fwhm_key='FWHM_IMAGE', verbose=True, visualize=False, save_fig=False)
- photometric_calibration(target_img: Union[ezphot.imageobjects.scienceimage.ScienceImage, ezphot.imageobjects.referenceimage.ReferenceImage, ezphot.imageobjects.calibrationimage.CalibrationImage], target_catalog: ezphot.dataobjects.catalog.Catalog, catalog_type: str = 'GAIAXP', max_distance_second: float = 1.0, calculate_color_terms: bool = True, calculate_mag_terms: bool = True, mag_lower: float = 13, mag_upper: float = 15, dynamic_mag_range: bool = True, classstar_lower: float = 0.8, elongation_upper: float = 1.7, elongation_sigma: float = 5, fwhm_lower: float = 1, fwhm_sigma: float = 5, flag_upper: int = 1, maskflag_upper: int = 1, inner_fraction: float = 0.7, isolation_radius: float = 10.0, magnitude_key: str = 'MAG_AUTO', fwhm_key: str = 'FWHM_IMAGE', x_key: str = 'X_IMAGE', y_key: str = 'Y_IMAGE', classstar_key: str = 'CLASS_STAR', elongation_key: str = 'ELONGATION', flag_key: str = 'FLAGS', maskflag_key: str = 'IMAFLAGS_ISO', save: bool = True, verbose: bool = True, visualize: bool = True, save_fig: bool = False, save_refcat: bool = True, **kwargs)
- select_stars(target_catalog: ezphot.dataobjects.catalog.Catalog, mag_lower: float = None, mag_upper: float = None, classstar_lower: float = 0.8, elongation_upper: float = 1.5, elongation_sigma: float = 5, fwhm_lower: float = 1, fwhm_upper: float = 15, fwhm_sigma: float = 5, flag_upper: int = 1, maskflag_upper: int = 1, inner_fraction: float = 0.7, isolation_radius: float = 5.0, save: bool = False, verbose: bool = True, visualize: bool = True, save_fig: bool = False, magnitude_key: str = 'MAG_AUTO', fwhm_key: str = 'FWHM_IMAGE', x_key: str = 'X_IMAGE', y_key: str = 'Y_IMAGE', classstar_key: str = 'CLASS_STAR', elongation_key: str = 'ELONGATION', flag_key: str = 'FLAGS', maskflag_key: str = 'IMAFLAGS_ISO')
[5]:
target_img, target_catalog_all, target_catalog_ref = photcal.photometric_calibration(
    target_img = target_img,
    target_catalog = target_catalog,
    catalog_type = 'GAIAXP', # GAIAXP or APASS or PS1 or SMSS or SDSS
    max_distance_second = 1.0,
    calculate_color_terms = True,
    calculate_mag_terms = True,
    mag_lower = 13,
    mag_upper = 15,
    dynamic_mag_range = True,
    classstar_lower = 0.8,
    elongation_upper = 1.7,
    elongation_sigma = 5,
    fwhm_lower = 1,
    fwhm_sigma = 5,
    flag_upper = 1,
    maskflag_upper = 1,
    inner_fraction = 0.7,
    isolation_radius = 10.0,
    magnitude_key = 'MAG_AUTO',
    fwhm_key = 'FWHM_IMAGE',
    x_key = 'X_IMAGE',
    y_key = 'Y_IMAGE',
    classstar_key = 'CLASS_STAR',
    elongation_key = 'ELONGATION',
    flag_key = 'FLAGS',
    maskflag_key = 'IMAFLAGS_ISO',
    save = False,
    verbose = False,
    visualize = True,
    save_fig = False,
    save_refcat = True
)

../_images/example_photometriccalibration_10_0.png
../_images/example_photometriccalibration_10_1.png
../_images/example_photometriccalibration_10_2.png
../_images/example_photometriccalibration_10_3.png
../_images/example_photometriccalibration_10_4.png
../_images/example_photometriccalibration_10_5.png
../_images/example_photometriccalibration_10_6.png
../_images/example_photometriccalibration_10_7.png
../_images/example_photometriccalibration_10_8.png
[6]:
print('SEEING: ', target_img.header['SEEING'])
print('SKYSIG: ', target_img.header['SKYSIG'])
print('ZP_APER_1: ', target_img.header['ZP_APER_1'])
print('ZP_APER_2: ', target_img.header['ZP_APER_2'])
print('UL5SKY_APER_1: ', target_img.header['UL5SKY_APER_1'])
print('UL5SKY_APER_2: ', target_img.header['UL5SKY_APER_2'])

SEEING:  3.015620080405407
SKYSIG:  39.7305
ZP_APER_1:  26.302696857378585
ZP_APER_2:  26.41774918536101
UL5SKY_APER_1:  17.837091470084452
UL5SKY_APER_2:  17.564888898102517
[7]:
target_catalog.data['MAG_AUTO', 'MAGSKY_AUTO']
[7]:
Table length=2440
MAG_AUTOMAGSKY_AUTO
float64float64
-11.46614.975660202152492
-11.52814.91366020215249
-11.320415.121260202152492
-13.669312.772360202152491
-9.609516.83216020215249
-9.188817.25286020215249
-10.213616.22806020215249
-9.704816.736860202152492
-11.251815.189860202152492
......
-10.052516.38916020215249
-10.374216.06746020215249
-11.478914.962760202152491
-11.290415.151260202152491
-11.719114.722560202152492
-9.628816.812860202152493
-9.363217.078460202152492
-8.998417.44326020215249
-9.087417.35426020215249
-11.587514.85416020215249
[9]:
# Run for all target_imglist with multiprocessing
from multiprocessing import Pool
from tqdm import tqdm

def photometriccalibration(target_img):
    photcal.photometric_calibration(
        target_img = target_img,
        target_catalog = target_img.catalog,
        catalog_type = 'GAIAXP', # GAIAXP or APASS or PS1 or SMSS or SDSS
        max_distance_second = 1.0,
        calculate_color_terms = True,
        calculate_mag_terms = True,
        mag_lower = 13,
        mag_upper = 15,
        dynamic_mag_range = True,
        classstar_lower = 0.8,
        elongation_upper = 1.7,
        elongation_sigma = 5,
        fwhm_lower = 1,
        fwhm_sigma = 5,
        flag_upper = 1,
        maskflag_upper = 1,
        inner_fraction = 0.7,
        isolation_radius = 10.0,
        magnitude_key = 'MAG_AUTO',
        fwhm_key = 'FWHM_IMAGE',
        x_key = 'X_IMAGE',
        y_key = 'Y_IMAGE',
        classstar_key = 'CLASS_STAR',
        elongation_key = 'ELONGATION',
        flag_key = 'FLAGS',
        maskflag_key = 'IMAFLAGS_ISO',
        save = True,
        verbose = False,
        visualize = False,
        save_fig = False,
        save_refcat = True
    )

# for target_img in tqdm(target_imglist, desc="Photometric Calibration..."):
#     photometriccalibration(target_img)

with Pool(processes = 16) as pool:
    # Use tqdm with imap to show progress
    list(tqdm(pool.imap(photometriccalibration, target_imglist),
              total=len(target_imglist),
              desc="Photometric Calibration..."))
Photometric Calibration...: 100%|██████████| 90/90 [00:20<00:00,  4.31it/s]

After calculation of Catalog with save option as “TRUE”, you can access to the catalogs easily from DataBrowser

[13]:
databrowser.objname = 'T00528'
databrowser.filter = 'm600'
target_catalogset = databrowser.search('*.cat', 'catalog')
target_cataloglist = target_catalogset.target_catalogs
[INFO] Found 90 files matching '/home/hhchoi1022/ezphot/data/scidata/*/*/T00528/*/m600/*.cat'
Loading Catalogs: 100%|██████████| 90/90 [00:00<00:00, 110.93it/s]
[16]:
for target_catalog in target_cataloglist[:10]:
    print('Number of sources: ', len(target_catalog.data))
Number of sources:  2015
Number of sources:  2173
Number of sources:  3128
Number of sources:  2295
Number of sources:  3270
Number of sources:  2673
Number of sources:  2619
Number of sources:  3812
Number of sources:  3237
Number of sources:  3251