303.1. Galaxy photometry¶
303.1. Galaxy photometry¶
Data Release: Data Preview 1
Container Size: large
LSST Science Pipelines version: r29.1.1
Last verified to run: 2025-06-28
Repository: github.com/lsst/tutorial-notebooks
Learning objective: Explore the available measurements of galaxy photometry produced by the LSST pipelines and their applications.
LSST data products: Object
table
Packages: lsst.rsp.get_tap_service
Credit: This notebook benefitted from an earlier exploration of simulated data and notebook development by Melissa Graham and Dan Taranu, helpful discussions with Jim Bosch, and ideas from Douglas Tucker.
Get Support: Everyone is encouraged to ask questions or raise issues in the Support Category of the Rubin Community Forum. Rubin staff will respond to all questions posted there.
1. Introduction¶
Photometry is the measurement of how much light is apparent from astronomical sources. The amount of light arriving on the telescope from the object is typically referred to as the flux density, or apparent magnitude (depending on units). Flux density is defined as the amount of energy arriving on the telescope per unit area, per unit time, per unit frequency (or wavelength) of the light.
The LSST Science Pipelines makes a variety of photometric measurements for point-like and extended sources. This notebook will teach the user about the automated photometry measurements for extended sources that are measured on the deepCoadd images and appear in the Object Catalog as part of the LSST pipelines data products.
The photometry measurements in the catalogs are flux densities in units of nano-Jansky [nJy]. 1 Jy = 10^{-23} ergs/s/cm^2/Hz.
1.1. Import packages¶
Import numpy
, a fundamental package for scientific computing with arrays in Python
(numpy.org), and
matplotlib
, a comprehensive library for data visualization
(matplotlib.org;
matplotlib gallery).
From the lsst
package, import modules for accessing the Table Access Protocol (TAP) service,
the butler, and image display functions from the LSST Science Pipelines (pipelines.lsst.io).
import numpy as np
import matplotlib.pyplot as plt
from lsst.rsp import get_tap_service
from scipy.stats import binned_statistic
1.2. Define parameters and functions¶
Get an instance of the TAP service, and assert that it exists.
service = get_tap_service("tap")
assert service is not None
2. Types of photometry¶
This section will explore photometry measurements produced by the LSST pipelines, and provide some guidance for which are optimal for various applications for science with galaxies.
2.1. Explore the schema¶
Numerous photometry measurements are produced by the LSST Pipelines. Two types of photometry are in the object table. The first are total fluxes (see Section 3), which aim to approximate (or model) all of the light coming from object. The second class of fluxes are measured inside an on-sky aperture but not corrected for flux that may fall outside: thus they are apparent fluxes but do not recover the intrisic (total) flux (see Section 4 and 5). The apparent fluxes are optimized for other purposes, such as for measuring accurate light profiles or accurate colors.
Schema for the object catalog for DP1 is available here. It lists the catalog header and brief explanation of the parameters.
First, see what is available in the object table by querying the tap_schema
columns, and printing all the parameters available related to "Flux" measured in the i-band (as an example). For clarity, the return also omits errors and flags associated with the photometric measurements outlined in section 1.1.
query = "SELECT column_name, datatype, description, unit " \
"FROM tap_schema.columns " \
"WHERE table_name = 'dp1.Object'"
results = service.search(query).to_table()
search_string = 'Flux'
band = 'i_'
exclude1 = 'Err'
exclude2 = 'flag'
for cname in results['column_name']:
if cname.find(search_string) > -1 and cname.find(band) > -1 and \
cname.find(exclude1) == -1 and cname.find(exclude2) == -1:
print(cname)
i_ap03Flux i_ap06Flux i_ap09Flux i_ap12Flux i_ap17Flux i_ap25Flux i_ap35Flux i_ap50Flux i_ap70Flux i_bdFluxB i_bdFluxD i_calibFlux i_cModelFlux i_cModelFlux_inner i_deblend_zeroFlux i_free_cModelFlux i_free_cModelFlux_inner i_free_psfFlux i_gaap0p7Flux i_gaap1p0Flux i_gaap1p5Flux i_gaap2p5Flux i_gaap3p0Flux i_gaapOptimalFlux i_gaapPsfFlux i_kronFlux i_psfFlux i_psfFlux_area i_sersicFlux
The object catalog also has pre-computed AB magnitudes (Mag
columns) for cModel and PSF. Query the tap_schema
columns, and print all the parameters available related to Mag
measured in the i-band.
search_string = 'Mag'
band = 'i_'
exclude1 = 'Err'
for cname in results['column_name']:
if cname.find(search_string) > -1 and cname.find(band) > -1 and \
cname.find(exclude1) == -1:
print(cname)
i_cModelMag i_psfMag
2.2. Select a galaxy sample¶
Below, query the DP1 objectTable
for a selection of photometric measurements.
Limit the search to contain galaxies using the i_extendedness
flag (which will exclude point sources). Further, identify objects which have been detected at high signal to noise > 20 and whose photometric measurements have not been flagged as having an issue (i_kronFlux_flag
or i_cModel_flag
or sersic_no_data_flag
= 0 means the photometry is ok). Also exclude very bright galaxies (i-band magnitude < 20).
Search for the sample using the DP1 imaging obtained in the Extended Chandra Deep Field South (ECDFS; center ra, dec = 53.2, -28.1 in degrees) which was one of the deepest imaging obtained as part of DP1.
target_ra = 53.2
target_dec = -28.1
query = "SELECT obj.objectId, obj.coord_ra, obj.coord_dec, " + \
"obj.detect_fromBlend, obj.detect_isIsolated, " + \
"obj.i_blendedness, obj.i_extendedness, " + \
"obj.i_kronFlux, obj.i_kronFluxErr, obj.i_kronRad, " + \
"obj.i_cModelFlux, obj.i_cModelFluxErr, obj.i_gaap1p0Flux, " + \
"obj.g_gaap1p0Flux, obj.g_gaap3p0Flux, obj.sersic_index, " + \
"obj.i_sersicFlux, obj.i_bdFluxB, obj.i_bdFluxD, " + \
"obj.i_kronFlux_flag, obj.i_cModel_flag, obj.sersic_no_data_flag, " + \
"obj.shape_xx, obj.shape_xy, obj.shape_yy, " + \
"obj.i_ap03Flux, obj.i_ap06Flux, obj.i_ap09Flux, obj.i_ap12Flux, " + \
"obj.i_ap17Flux, obj.i_ap25Flux, obj.i_ap35Flux, obj.i_ap50Flux " + \
"FROM dp1.Object AS obj " + \
"WHERE (obj.i_cModelFlux/obj.i_cModelFluxErr > 20) AND " + \
"(obj.i_extendedness = 1) AND (obj.sersic_no_data_flag = 0) AND " + \
"(obj.i_kronFlux_flag = 0) AND (obj.i_cModel_flag = 0) AND " + \
"(scisql_nanojanskyToAbMag(obj.i_cModelFlux) > 20) AND " + \
"CONTAINS(POINT('ICRS', obj.coord_ra, obj.coord_dec), " + \
"CIRCLE('ICRS',"+str(target_ra)+","+str(target_dec)+", 0.1)) = 1 "
job = service.submit_job(query)
job.run()
job.wait(phases=['COMPLETED', 'ERROR'])
print('Job phase is', job.phase)
Job phase is COMPLETED
if job.phase == 'ERROR':
job.raise_if_error()
assert job.phase == 'COMPLETED'
Print the results of the search query.
results = job.fetch_result()
tab = results.to_table()
tab
objectId | coord_ra | coord_dec | detect_fromBlend | detect_isIsolated | i_blendedness | i_extendedness | i_kronFlux | i_kronFluxErr | i_kronRad | i_cModelFlux | i_cModelFluxErr | i_gaap1p0Flux | g_gaap1p0Flux | g_gaap3p0Flux | sersic_index | i_sersicFlux | i_bdFluxB | i_bdFluxD | i_kronFlux_flag | i_cModel_flag | sersic_no_data_flag | shape_xx | shape_xy | shape_yy | i_ap03Flux | i_ap06Flux | i_ap09Flux | i_ap12Flux | i_ap17Flux | i_ap25Flux | i_ap35Flux | i_ap50Flux |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
deg | deg | nJy | nJy | nJy | nJy | nJy | nJy | nJy | nJy | nJy | nJy | pix2 | pix2 | pix2 | nJy | nJy | nJy | nJy | nJy | nJy | nJy | nJy | ||||||||||
int64 | float64 | float64 | bool | bool | float32 | float32 | float32 | float32 | float32 | float32 | float32 | float32 | float32 | float32 | float32 | float32 | float32 | float32 | bool | bool | bool | float32 | float32 | float32 | float32 | float32 | float32 | float32 | float32 | float32 | float32 | float32 |
611254385447554223 | 53.10869631730936 | -28.053125495747967 | True | False | 0.00128771 | 1.0 | 679.518 | 44.6638 | 4.18296 | 595.586 | 21.2605 | 595.558 | 323.595 | 521.861 | 5.81783 | 643.027 | 606.892 | 596.97 | False | False | False | 6.25636 | -0.0957992 | 4.90198 | 311.231 | 517.103 | 633.824 | 651.459 | 830.618 | 1100.58 | 1536.7 | 2793.37 |
611254385447554161 | 53.18305146638707 | -28.053084728337446 | True | False | 0.000398492 | 1.0 | 532.999 | 28.4107 | 2.66188 | 566.081 | 20.01 | 547.475 | 538.396 | 488.367 | 3.4168 | 565.042 | 565.1 | 563.317 | False | False | False | 4.61214 | 0.849219 | 4.48061 | 310.724 | 502.121 | 519.555 | 511.267 | 425.225 | 261.886 | 59.8264 | 508.253 |
611254385447554139 | 53.267054271806835 | -28.051368502857912 | True | False | 0.000671823 | 1.0 | 5343.76 | 58.4422 | 5.52311 | 5496.12 | 36.1533 | 3498.15 | 1694.65 | 2483.27 | 0.5 | 5320.93 | 8204.1 | 5508.75 | False | False | False | 26.3779 | 10.2305 | 13.851 | 1244.73 | 3119.76 | 4417.99 | 4965.76 | 5175.35 | 5185.55 | 5344.77 | 5741.69 |
611254385447551834 | 53.227229102821 | -28.056411996175036 | True | False | 3.35978e-06 | 1.0 | 9711.28 | 46.2747 | 4.28288 | 9639.26 | 26.4966 | 8314.83 | 2191.77 | 2509.55 | 4.27966 | 9765.95 | 9861.68 | 8924.62 | False | False | False | 7.48778 | 0.681119 | 6.26271 | 4029.71 | 7515.71 | 8916.6 | 9445.26 | 9760.3 | 9756.91 | 9708.24 | 9958.67 |
611254385447554141 | 53.27044067864118 | -28.053243991994698 | True | False | 0.00711502 | 1.0 | 568.7 | 42.0168 | 4.00438 | 581.152 | 27.5372 | 478.966 | 233.165 | 283.162 | 0.549193 | 550.648 | 698.703 | 582.15 | False | False | False | 9.59351 | 2.41451 | 9.44864 | 189.716 | 452.417 | 553.997 | 579.046 | 512.531 | 556.745 | 789.647 | 1553.42 |
611254385447554140 | 53.269631050118406 | -28.052501467520017 | True | False | 0.000276643 | 1.0 | 1710.96 | 36.1473 | 3.45227 | 1790.86 | 24.1964 | 1581.16 | 629.978 | 711.066 | 1.34978 | 1721.5 | 1917.13 | 1728.22 | False | False | False | 6.43302 | -0.00511905 | 7.13242 | 785.882 | 1467.15 | 1648.0 | 1681.02 | 1642.01 | 1714.3 | 2117.16 | 2668.49 |
611254385447554228 | 53.25793176364599 | -28.049962698629642 | True | False | 0.0485429 | 1.0 | 513.095 | 29.5869 | 2.79393 | 587.448 | 25.6911 | 463.779 | 405.741 | 467.643 | 0.71116 | 555.508 | 652.091 | 588.366 | False | False | False | 13.3603 | -2.61231 | 4.18241 | 231.308 | 437.323 | 468.776 | 454.308 | 442.702 | 510.611 | 886.416 | 1710.06 |
611254385447551831 | 53.201965028385715 | -28.056821827562683 | True | False | 1.20921e-06 | 1.0 | 21295.1 | 58.172 | 5.34424 | 21976.1 | 36.4594 | 15245.5 | 6830.81 | 9055.51 | 0.996813 | 21015.6 | 30859.5 | 20913.9 | False | False | False | 12.9483 | 0.648399 | 13.4246 | 5856.3 | 13818.5 | 18349.4 | 20060.7 | 20871.2 | 21129.5 | 21190.3 | 21894.8 |
611254385447551838 | 53.22529696514233 | -28.055694487895337 | True | False | 0.000602499 | 1.0 | 7688.19 | 48.1727 | 4.45434 | 7589.28 | 29.8316 | 6100.28 | 2200.22 | 2624.11 | 0.783994 | 7386.19 | 10221.9 | 7602.27 | False | False | False | 9.98393 | 0.463143 | 10.9208 | 2518.67 | 5628.62 | 6956.56 | 7429.7 | 7522.09 | 7449.24 | 7732.29 | 8699.81 |
611254385447554104 | 53.12266314046538 | -28.054220435503947 | True | False | 0.000254243 | 1.0 | 5136.9 | 41.7102 | 3.83795 | 4899.86 | 22.5876 | 4727.28 | 446.839 | 711.055 | 5.9103 | 4948.75 | 4897.74 | 4788.6 | False | False | False | 5.32302 | -0.130744 | 5.39459 | 2523.94 | 4264.5 | 4848.37 | 5090.48 | 5269.75 | 5729.19 | 6900.08 | 9158.12 |
611254385447554241 | 53.19798847594119 | -28.04966428703969 | True | False | 1.48611e-06 | 1.0 | 22486.8 | 53.7562 | 4.81942 | 23836.2 | 33.8803 | 17781.0 | 4051.11 | 4632.6 | 3.04724 | 22064.1 | 24031.7 | 20072.1 | False | False | False | 8.34943 | 0.104549 | 8.12703 | 8121.39 | 16029.1 | 19846.6 | 21513.6 | 22484.9 | 22683.7 | 22574.4 | 22795.7 |
611254385447554242 | 53.19787259253262 | -28.051708204949804 | True | False | 0.0192819 | 1.0 | 602.578 | 39.6314 | 3.65778 | 653.073 | 23.7232 | 590.743 | 92.4249 | 70.9896 | 0.707073 | 621.347 | 707.003 | 654.444 | False | False | False | 5.51919 | 0.313247 | 7.24736 | 305.596 | 540.286 | 585.583 | 615.929 | 546.226 | 403.272 | 452.35 | 977.859 |
611254385447554205 | 53.18740267908544 | -28.05215632496554 | True | False | 0.0493204 | 1.0 | 724.234 | 48.0091 | 4.41479 | 582.883 | 22.0818 | 578.205 | 237.98 | 276.816 | 4.99805 | 717.735 | 591.344 | 584.462 | False | False | False | 6.84894 | -1.01006 | 6.16066 | 284.424 | 495.889 | 616.091 | 692.644 | 733.975 | 564.792 | 817.846 | 726.344 |
611254385447554123 | 53.27445634665745 | -28.050913572463298 | True | False | 0.0371674 | 1.0 | 3323.51 | 35.5173 | 3.34283 | 3336.79 | 21.2586 | 3245.07 | 1181.65 | 1327.32 | 3.80918 | 3316.66 | 3385.48 | 3342.1 | False | False | False | 5.26848 | 0.0857561 | 5.01997 | 1757.78 | 2938.54 | 3217.27 | 3319.98 | 3417.76 | 3759.56 | 4527.05 | 4995.77 |
611254385447554206 | 53.18605310032971 | -28.053176268673266 | True | False | 0.00181571 | 1.0 | 516.695 | 36.0449 | 3.37074 | 581.819 | 24.2313 | 508.144 | 298.895 | 349.047 | 0.597296 | 566.981 | 634.842 | 583.091 | False | False | False | 5.65659 | -2.87742 | 8.37508 | 253.333 | 477.607 | 527.069 | 520.388 | 506.917 | 622.501 | 656.109 | 1381.3 |
611254385447554124 | 53.274292757382796 | -28.05144142453733 | True | False | 0.176538 | 1.0 | 3208.97 | 63.484 | 5.91304 | 3542.76 | 41.5646 | 1988.86 | 380.927 | 686.388 | 1.35617 | 3298.86 | 4309.92 | 2996.7 | False | False | False | 19.1296 | -9.64978 | 16.3298 | 749.486 | 1757.76 | 2441.46 | 2824.87 | 3037.29 | 3163.53 | 3631.84 | 4359.36 |
611254385447554204 | 53.18729553150917 | -28.050857328638152 | True | False | 0.0165683 | 1.0 | 517.215 | 29.028 | 2.71252 | 535.138 | 20.4803 | 527.271 | 114.516 | 105.132 | 3.13241 | 572.038 | 539.434 | 536.379 | False | False | False | 4.96834 | -0.576652 | 4.93676 | 298.18 | 473.674 | 526.537 | 511.172 | 371.642 | 369.043 | 279.313 | 383.64 |
611254385447554122 | 53.27615888368163 | -28.052242554408213 | True | False | 4.94149e-06 | 1.0 | 3762.0 | 35.7191 | 3.3687 | 3735.36 | 20.0232 | 3731.29 | 427.744 | 629.801 | 5.99983 | 3675.56 | 3735.24 | 3718.81 | False | False | False | 4.42227 | -0.26602 | 4.12684 | 2093.97 | 3329.81 | 3669.1 | 3810.48 | 3911.43 | 4092.4 | 4825.92 | 6436.27 |
611254385447551899 | 53.22627037217966 | -28.05750282907624 | True | False | 0.00341949 | 1.0 | 1174.18 | 130.805 | 12.2361 | 586.652 | 19.4955 | 552.129 | 371.75 | 423.974 | 3.60652 | 579.817 | 585.452 | 587.68 | False | False | False | 4.6436 | -0.255525 | 3.73891 | 338.23 | 496.492 | 509.056 | 482.301 | 417.401 | 752.129 | 1350.43 | 2594.11 |
611254385447554135 | 53.26214382481303 | -28.05354828253407 | True | False | 0.000508224 | 1.0 | 1077.8 | 29.1406 | 2.77819 | 1108.89 | 19.5213 | 1106.31 | 541.449 | 477.779 | 3.92326 | 1114.05 | 1107.1 | 1105.32 | False | False | False | 4.50477 | -0.127924 | 4.2234 | 627.233 | 989.846 | 1097.08 | 1075.1 | 1031.83 | 913.57 | 616.248 | 398.73 |
611254385447554196 | 53.19271630768381 | -28.0507113419749 | True | False | 9.90465e-05 | 1.0 | 441.457 | 27.2351 | 2.53009 | 491.141 | 24.1534 | 435.167 | 488.543 | 479.389 | 0.557433 | 473.245 | 548.61 | 492.121 | False | False | False | 6.33181 | 0.65002 | 7.22215 | 222.63 | 411.922 | 450.951 | 368.797 | 231.361 | 119.812 | 123.499 | 594.508 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
611254385447552531 | 53.10232073536453 | -28.071125920292545 | True | False | 0.00124978 | 1.0 | 1424.28 | 44.2472 | 4.02292 | 1458.8 | 25.3005 | 1301.52 | 710.577 | 952.774 | 0.826829 | 1445.08 | 1649.54 | 1463.05 | False | False | False | 8.26103 | -0.626174 | 6.43914 | 637.118 | 1231.1 | 1347.22 | 1357.47 | 1445.67 | 1582.47 | 2063.62 | 3467.53 |
611254385447552523 | 53.12531670538563 | -28.071171668533715 | True | False | 0.00309558 | 1.0 | 1213.95 | 145.799 | 13.5867 | 528.288 | 20.4733 | 526.758 | 196.721 | 269.035 | 5.55611 | 569.034 | 527.444 | 514.199 | False | False | False | 4.49449 | -0.532676 | 5.9134 | 278.879 | 483.962 | 540.068 | 509.988 | 536.024 | 775.277 | 1209.33 | 2697.61 |
611254385447552597 | 53.27600912381538 | -28.06764188722875 | True | False | 0.000756358 | 1.0 | 4784.79 | 45.8143 | 4.25567 | 4741.39 | 26.7439 | 4100.86 | 1180.83 | 1324.71 | 0.854463 | 4669.24 | 5710.86 | 4751.11 | False | False | False | 7.93234 | 0.176736 | 9.202 | 1863.18 | 3805.36 | 4458.22 | 4668.91 | 4767.86 | 5022.52 | 5255.22 | 5385.75 |
611254385447552522 | 53.12337572660797 | -28.068832482246695 | True | False | 0.0327539 | 1.0 | 594.999 | 33.7914 | 3.14529 | 608.987 | 22.6494 | 564.397 | 282.763 | 374.679 | 5.44741 | 590.66 | 626.469 | 596.157 | False | False | False | 5.53855 | 1.02019 | 5.96124 | 298.829 | 520.929 | 564.449 | 622.267 | 616.948 | 686.927 | 1302.88 | 2888.08 |
611254385447552576 | 53.149328217834416 | -28.06949608034701 | True | False | 0.0368712 | 1.0 | 538.089 | 49.5495 | 4.5926 | 546.663 | 25.9743 | 463.176 | 343.255 | 342.068 | 0.663387 | 518.914 | 583.598 | 520.749 | False | False | False | 7.99643 | -2.39615 | 7.07664 | 222.275 | 427.917 | 505.496 | 498.32 | 500.761 | 586.627 | 756.411 | 1284.24 |
611254385447552575 | 53.14334357220262 | -28.065386143361504 | True | False | 0.0100005 | 1.0 | 788.466 | 44.1251 | 4.07115 | 721.88 | 22.1866 | 700.612 | 351.228 | 384.45 | 3.32089 | 781.99 | 721.419 | 703.372 | False | False | False | 5.77571 | -0.0577161 | 5.35657 | 366.737 | 623.035 | 732.807 | 777.303 | 758.878 | 866.579 | 1107.96 | 1854.28 |
611254385447552573 | 53.144680640657384 | -28.069420605093484 | True | False | 0.000993283 | 1.0 | 1038.69 | 37.548 | 3.41437 | 1070.61 | 23.395 | 998.622 | 472.391 | 539.967 | 0.783066 | 1056.13 | 1112.77 | 1073.24 | False | False | False | 6.45416 | -0.691767 | 5.81087 | 515.28 | 915.551 | 1007.16 | 1044.11 | 1077.26 | 1199.0 | 1689.13 | 2415.64 |
611254385447552565 | 53.22973750473511 | -28.069904710804106 | True | False | 0.0791 | 1.0 | 371.379 | 26.516 | 2.53569 | 407.326 | 20.0396 | 377.118 | 319.049 | 186.778 | 1.49635 | 417.98 | 409.1 | 406.964 | False | False | False | 6.55402 | -0.855142 | 3.50881 | 220.876 | 356.916 | 337.978 | 277.651 | 113.311 | -103.123 | -102.196 | -1841.12 |
611254385447552472 | 53.110236035250615 | -28.072001503975915 | True | False | 0.0 | 1.0 | 1943.8 | 69.4884 | 6.29995 | 2425.32 | 48.1006 | 1233.85 | 544.491 | 882.393 | 2.03612 | 1963.19 | 2679.86 | 1796.19 | False | False | False | 11.3384 | -1.03727 | 17.5187 | 482.378 | 1105.6 | 1485.86 | 1677.45 | 1883.14 | 1975.3 | 2647.86 | 4026.88 |
611254385447552467 | 53.1846095347156 | -28.07135949092992 | True | False | 9.85014e-05 | 1.0 | 625.922 | 27.2648 | 2.5295 | 646.848 | 20.2868 | 626.036 | 516.639 | 371.65 | 3.21739 | 630.879 | 649.259 | 648.24 | False | False | False | 4.75672 | -0.0107711 | 4.41346 | 365.959 | 589.476 | 580.243 | 570.472 | 564.972 | 530.049 | 670.677 | 529.982 |
611254385447552456 | 53.157342873316026 | -28.072831260171238 | True | False | 0.0 | 1.0 | 1360.44 | 30.7627 | 2.91844 | 1413.55 | 20.6179 | 1356.24 | 458.1 | 282.723 | 3.20695 | 1376.49 | 1431.65 | 1417.5 | False | False | False | 5.30591 | -0.0532112 | 4.58454 | 764.061 | 1256.18 | 1304.34 | 1298.8 | 1200.11 | 1017.6 | 961.392 | 1897.37 |
611254385447552452 | 53.171438765547585 | -28.07139019052004 | True | False | 0.0412914 | 1.0 | 495.185 | 29.7965 | 2.86541 | 530.789 | 20.6604 | 498.439 | 281.269 | 283.766 | 4.06011 | 485.646 | 532.831 | 532.292 | False | False | False | 5.34463 | -1.02388 | 5.03118 | 266.57 | 456.93 | 483.566 | 457.137 | 533.437 | 869.55 | 1442.27 | 2593.79 |
611254385447552451 | 53.171177500197494 | -28.071900270896133 | True | False | 0.0112712 | 1.0 | 2163.81 | 165.263 | 15.6413 | 1041.28 | 23.6169 | 917.086 | 728.393 | 733.866 | 0.523145 | 982.288 | 1173.37 | 1043.88 | False | False | False | 8.6992 | 0.561871 | 5.34523 | 462.753 | 870.207 | 935.496 | 912.33 | 818.485 | 1162.56 | 1803.48 | 3141.48 |
611254385447552450 | 53.172451486974246 | -28.070541377017708 | True | False | 2.3447e-05 | 1.0 | 1265.19 | 49.2118 | 4.6542 | 1146.29 | 22.1979 | 1091.98 | 410.265 | 332.011 | 2.54998 | 1085.05 | 1215.04 | 1149.0 | False | False | False | 5.43607 | -0.530073 | 7.04628 | 561.934 | 981.688 | 1152.19 | 1198.1 | 1318.41 | 1476.91 | 1759.57 | 2884.61 |
611254385447552448 | 53.09260310844842 | -28.072957320915826 | True | False | 0.0 | 1.0 | 882.715 | 75.1794 | 6.75106 | 1014.83 | 45.3413 | 552.522 | 177.544 | 459.346 | 2.88355 | 1576.0 | 1191.35 | 877.93 | False | False | False | 22.7033 | 6.42909 | 16.8103 | 203.933 | 461.326 | 742.684 | 822.812 | 826.995 | 1033.78 | 1495.58 | 2905.45 |
611254385447552521 | 53.12325137294433 | -28.06943975277864 | True | False | 0.0134908 | 1.0 | 1074.17 | 43.9408 | 4.05615 | 1108.47 | 27.592 | 920.828 | 232.832 | 341.278 | 0.542973 | 1065.68 | 1320.33 | 1111.55 | False | False | False | 8.95975 | 4.41972 | 10.9347 | 396.406 | 869.383 | 1006.53 | 1101.92 | 1087.21 | 1229.28 | 1702.44 | 3254.23 |
611254385447552520 | 53.11974324697804 | -28.06855973549187 | True | False | 0.000608284 | 1.0 | 1556.27 | 34.8529 | 3.23043 | 1545.75 | 21.0645 | 1508.95 | 529.894 | 582.688 | 3.80855 | 1550.2 | 1561.15 | 1550.35 | False | False | False | 5.23609 | -0.0684724 | 4.8296 | 831.647 | 1369.12 | 1478.12 | 1483.2 | 1564.84 | 1615.43 | 1889.9 | 3084.31 |
611254385447552485 | 53.250812115601775 | -28.071190299802964 | True | False | 0.00175079 | 1.0 | 1387.81 | 170.277 | 15.8654 | 697.456 | 24.0375 | 640.237 | 228.953 | 303.505 | 1.25126 | 715.059 | 790.096 | 698.998 | False | False | False | 6.80214 | 0.473536 | 7.22015 | 314.034 | 575.986 | 688.153 | 721.768 | 551.752 | 554.656 | 1039.52 | 2176.38 |
611254385447552484 | 53.24788686819021 | -28.071841222894708 | True | False | 0.0466063 | 1.0 | 415.615 | 226.925 | 21.1498 | 1332.8 | 31.8995 | 921.404 | 151.267 | 101.387 | 0.639742 | 1265.72 | 1736.48 | 1336.02 | False | False | False | 14.9153 | -10.5234 | 17.7759 | 368.063 | 821.602 | 1085.87 | 1149.92 | 1154.4 | 1131.46 | 858.996 | 636.842 |
611254385447551661 | 53.209737824910434 | -28.08560116229577 | True | False | 0.00521152 | 1.0 | 502.076 | 30.235 | 2.92628 | 517.449 | 21.0958 | 495.69 | 369.682 | 572.744 | 4.54265 | 544.887 | 525.006 | 518.426 | False | False | False | 5.43713 | 0.270479 | 5.71433 | 263.547 | 444.431 | 504.853 | 517.896 | 510.125 | 692.481 | 965.381 | 1732.88 |
611254454167027263 | 53.08670555727182 | -28.10108225287607 | True | False | 0.000522459 | 1.0 | 1564.82 | 53.5773 | 4.93856 | 1649.54 | 30.9304 | 1221.0 | 838.929 | 1061.19 | 2.48241 | 1441.54 | 1647.82 | 1389.24 | False | False | False | 9.14919 | -1.80715 | 7.64448 | 559.678 | 1076.17 | 1390.73 | 1482.3 | 1598.18 | 1805.4 | 2453.47 | 3643.01 |
611254454167027838 | 53.086880615110765 | -28.098325429171854 | True | False | 4.75941e-05 | 1.0 | 8133.68 | 51.2046 | 4.67515 | 7883.01 | 28.4224 | 6646.55 | 1489.15 | 1955.14 | 1.01492 | 7991.58 | 9920.13 | 7903.67 | False | False | False | 9.49882 | -0.51753 | 9.14885 | 2917.34 | 6137.53 | 7388.04 | 7809.3 | 8098.28 | 8405.33 | 8897.98 | 10068.7 |
Below, convert the fluxes (units $nJy$) extracted from the objectTable
into AB magnitudes using: $m_{AB} = -2.5log( f_{nJy}) + 31.4$ (see e.g. AB Magnitudes Wikipedia page for the conversion between flux in Jy and AB magnitudes).
Warning: The following cell will produce warnings for invalid value encountered in log10, which happens if the source flux is negative. This occasionally happens from aperture photometry if the included pixels inside the aperture have negative values and can be safely ignored for this example. The log10 will return a NaN which can be filtered out later.
cmodel_mag = -2.50 * np.log10(tab['i_cModelFlux']) + 31.4
sersic_mag = -2.50 * np.log10(tab['i_sersicFlux']) + 31.4
bdFluxD_mag = -2.50 * np.log10(tab['i_bdFluxD']) + 31.4
bdFluxB_mag = -2.50 * np.log10(tab['i_bdFluxB']) + 31.4
ap06_mag = -2.50 * np.log10(tab['i_ap06Flux']) + 31.4
ap09_mag = -2.50 * np.log10(tab['i_ap09Flux']) + 31.4
ap17_mag = -2.50 * np.log10(tab['i_ap17Flux']) + 31.4
ap12_mag = -2.50 * np.log10(tab['i_ap12Flux']) + 31.4
ap35_mag = -2.50 * np.log10(tab['i_ap35Flux']) + 31.4
kron_mag = -2.50 * np.log10(tab['i_kronFlux']) + 31.4
gaap_mag = -2.50 * np.log10(tab['i_gaap1p0Flux']) + 31.4
/tmp/ipykernel_66304/3117612974.py:7: RuntimeWarning: invalid value encountered in log10 ap17_mag = -2.50 * np.log10(tab['i_ap17Flux']) + 31.4 /tmp/ipykernel_66304/3117612974.py:9: RuntimeWarning: invalid value encountered in log10 ap35_mag = -2.50 * np.log10(tab['i_ap35Flux']) + 31.4 /tmp/ipykernel_66304/3117612974.py:10: RuntimeWarning: invalid value encountered in log10 kron_mag = -2.50 * np.log10(tab['i_kronFlux']) + 31.4
Below, store two shape parameters that will be useful for interpreting photometric apertures. First, the Kron Radius, which is a good proxy for the size of the galaxy light profile. Then, the sersic index, which describes the shape of the light profile of galaxies.
i_kronRad = tab['i_kronRad']
sersic_index = tab['sersic_index']
3. Total fluxes¶
The following measurements are available: total fluxes from the sersic model (with shape parameters left free), from cModel (sum of bulge and disk sersic components fitted to the galaxy); and bulge/disk (BD) fluxes with sersic index fixed.
Sersic fluxes¶
This photometric measurement models all galaxies as a single Sersic profile and calculates its total flux according to the best fitting model. More information the sersic profile is available here.
The best fit sersic model is evaluated based on a model to all filters, and then the flux in each filter is calculated by integrating the galaxy light from the best fit model, assuming the best-fit sersic shape parameters.
<f>_sersicFlux : Flux from the final sersic fit. Forced on <f>-band.
<f>_sersicFluxErr : Uncertainty of <f>_sersicFlux
sersic_no_data_flag : Failure flag for <f>_sersicFlux
DP1 is the first Rubin data release that contains Sersic fluxes. cModel fluxes (see below) have seen more testing and been in use longer (and originate with SDSS). The LSST pipeline package responsible for sersic fluxes is called multiprofit
and documentation is available here.
Bulge/Disk (BD) fluxes¶
This is a photometric measurement similar to using a single Sersic profile, integrated to estimate the flux. But, rather than using the best fit sersic index obtained from modeling the 6 images in each filter, the BD fluxes fixes the sersic index n to either 1 (exponential disk) or 4 (de Vaucouleurs bulge).
<f>_bdFlux* : Flux from the final sersic fit. Forced on <f>-band. If * = D then this refers to disk and assumes sersic index n=1 (exponential profile). * = B refers to a bulge with de Vaucouleurs profile (n=4).
<f>_bdFlux*Err : Uncertainty of <f>_sersicFlux
Composite Model (CModel) fluxes¶
Similar in nature to those measured for SDSS (information available here) that will be familiar to SDSS users. In short, it is the linear combination of the best fit exponential (disk or D; sersic index n = 1) and de Vaucouleurs (bulge or B; sersic index n = 4) profiles. Thus, cModel is a good compromise between the BD fluxes that assume either a bulge or a disk.
<f>_cModelFlux : Flux from the final cmodel fit. Forced on <f>-band.
<f>_cModelFluxErr : Uncertainty of <f>_cModelFlux
<f>_cModel_flag : Failure flag for <f>_cModelFlux
For most cases the "fixed" cModel photometry (i.e. the catalog entries listed above) are preferred to that measured with more degrees of freedom labeled <f>_free_cModelFlux
. The difference is that the fixed ones above uses a reference band (recorded as refBand
in the schema) where the galaxy is well detected to determine the other parameters, which are then fixed when fitting for the flux in the other bands. The _free_cModelFlux
measurement allows all parameters to be free and independent in each filter. The fixed _cModelFlux
measurements are generally recommended for galaxy science applications where total flux measurements are needed (e.g. for intrinsic luminosity or mass).
In the Object
table, a pre-computed AB magnitude (<f>_cModelMag
) also exists for this measurement.
3.1. Comparing total fluxes¶
This section will make several plots that shows how the different photometric measurements compare.
First, compare cModelFlux
(two component bulge+disk sersic model flux) to sersicFlux
(single sersic model flux with shape parameters free), bdFluxB
(sersic with n=4) and bdFluxD
(sersic with n=1).
fig, (ax, ax2) = plt.subplots(ncols=2, nrows=1,
width_ratios=[0.8, 0.2], figsize=(10, 6))
bins = np.arange(16, 27, 1)
ylims = [-1.2, 1.2]
ax.plot(cmodel_mag, (cmodel_mag-bdFluxD_mag), 's', alpha=.3,
label='cModel-bdFluxD', color='blue')
x = cmodel_mag
y = (cmodel_mag-bdFluxD_mag)
bin_mean, bin_edge, binnum = binned_statistic(x, y,
statistic='median', bins=bins)
binctr = bin_edge[:-1] + (bin_edge[1:]-bin_edge[:-1])/2
ax.plot(binctr, bin_mean, color='k', lw=3, label=None, zorder=10)
ax.plot(binctr, bin_mean, color='blue', lw=2, label='bin median', zorder=11)
ax.plot(cmodel_mag, (cmodel_mag-bdFluxB_mag), '^', alpha=.3,
label='cModel-bdFluxB', color='r')
x = cmodel_mag
y = (cmodel_mag-bdFluxB_mag)
bin_mean, bin_edge, binnum = binned_statistic(x, y,
statistic='median', bins=bins)
binctr = bin_edge[:-1] + (bin_edge[1:]-bin_edge[:-1])/2
ax.plot(binctr, bin_mean, color='k', lw=3, label=None, zorder=10)
ax.plot(binctr, bin_mean, color='r', lw=2, label='bin median', zorder=11)
ax.plot(cmodel_mag, (cmodel_mag - sersic_mag), 'o', alpha=.3,
label='cModel - sersic', color='g')
x = cmodel_mag
y = (cmodel_mag-sersic_mag)
bin_mean, bin_edge, binnum = binned_statistic(x, y,
statistic='median', bins=bins)
binctr = bin_edge[:-1] + (bin_edge[1:]-bin_edge[:-1])/2
ax.plot(binctr, bin_mean, color='k', lw=3, label=None, zorder=10)
ax.plot(binctr, bin_mean, color='g', lw=2, label='bin median', zorder=11)
ax.axhline(0, linestyle='--')
ax.set_xlabel('cModel Magnitude')
ax.set_ylabel('cModel mag - other mag')
ax.set_ylim([-1, 1])
ax.legend()
ax2.hist((cmodel_mag-bdFluxD_mag), orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 40), align='mid',
histtype="step", color='blue', stacked=True, fill=False, label='bdFluxD')
ax2.hist((cmodel_mag-bdFluxB_mag), orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 40), align='mid',
histtype="step", color='r', stacked=True, fill=False, label='bdFluxB')
ax2.hist((cmodel_mag-sersic_mag), orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 40), align='mid',
histtype="step", color='g', stacked=True, fill=False, label='Sersic')
ax2.set_ylim(ylims)
ax2.axhline(0, linestyle='--', color='k')
ax.axhline(0, linestyle='--', color='k')
ax.set_xlabel('i-band AB magnitude [cModel]')
ax.set_ylabel('cModel mag - Other mag')
ax.set_ylim(ylims)
ax.legend()
ax2.legend()
<matplotlib.legend.Legend at 0x7e8623d88770>
Figure 1: Left panel: a plot comparing the magnitude difference between cModel and dbFluxD (blue), bdFluxB (red) and sersic (green) vs i-band magnitude as measured by cModel. Right panel: a histogram showing the difference in color between cModel and the three other photometric measurements, across all magnitudes. The sersic fluxes are in best agreement with cModel (smallest scatter in right panel) with the bdFluxB returning systematically fainter magnitudes, and bdFluxD returning systematically brighter magnitudes.
Below, explore how the BD fluxes compare to sersic fluxes as a function of the shape of the light profile, sersic index n.
fig, (ax, ax2) = plt.subplots(ncols=2, nrows=1,
width_ratios=[0.8, 0.2], figsize=(10, 6))
bins = np.arange(0, 7, 0.25)
ylims = [-1.2, 1.2]
ax.plot(sersic_index, (sersic_mag-bdFluxD_mag), 's', alpha=.3,
label='cModel-bdFluxD', color='blue')
x = sersic_index
y = (sersic_mag-bdFluxD_mag)
bin_mean, bin_edge, binnum = binned_statistic(x, y,
statistic='median', bins=bins)
binctr = bin_edge[:-1] + (bin_edge[1:]-bin_edge[:-1])/2
ax.plot(binctr, bin_mean, color='k', lw=3, label=None, zorder=10)
ax.plot(binctr, bin_mean, color='blue', lw=2, label='bin median', zorder=11)
ax.plot(sersic_index, (sersic_mag-bdFluxB_mag), '^', alpha=.3,
label='cModel-bdFluxB', color='r')
x = sersic_index
y = (sersic_mag-bdFluxB_mag)
bin_mean, bin_edge, binnum = binned_statistic(x, y,
statistic='median', bins=bins)
binctr = bin_edge[:-1] + (bin_edge[1:]-bin_edge[:-1])/2
ax.plot(binctr, bin_mean, color='k', lw=3, label=None, zorder=10)
ax.plot(binctr, bin_mean, color='r', lw=2, label='bin median', zorder=11)
ax.axhline(0, linestyle='--')
ax.set_ylabel('sersic mag - BD mag')
ax.set_ylim([-1, 1])
ax.legend()
ax2.hist((cmodel_mag-bdFluxD_mag), orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 40), align='mid',
histtype="step", color='blue', stacked=True, fill=False, label='bdFluxD')
ax2.hist((cmodel_mag-bdFluxB_mag), orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 40), align='mid',
histtype="step", color='r', stacked=True, fill=False, label='bdFluxB')
ax2.set_ylim(ylims)
ax2.axhline(0, linestyle='--', color='k')
ax.axhline(0, linestyle='--', color='k')
ax.set_xlabel('Sersic Index n')
ax.set_ylabel('Sersic mag - Other mag')
ax.set_ylim(ylims)
ax.set_xlim([0, 8])
ax.legend()
ax2.legend()
<matplotlib.legend.Legend at 0x7e861baf12e0>
Fig 2: Comparison of the sersic mag (flux measured with sersic parameters left free) with the bdFlux that is measured with sersic index fixed to either n=1 (D) or n=4 (B) as a function of sersic index n. Fixing the sersic index can inject scatter in the flux relative to leaving it free, but the sersic flux converges on bdFluxD(B) for n=1 and n=4.
4. Apparent fluxes¶
This section explores three types of apparent fluxes: Kron (elliptical apertures that typically includes more than 90% of intrinsic light), and aperture photometry (flux measured inside circles of varying size).
Here, apparent fluxes refers to photometry that are not corrected for flux outside of the measurement aperture (i.e. not corrected to be a total flux). These measurements have their own applications but should not be used to measure mass or luminosity.
Kron fluxes¶
A decent summary of Kron fluxes in the NED documentation. The aperture used for the fluxes is 2.5 x R1 where R1 is the luminosity weighted radius (also called "first moment"; Kron et al. 1980).
<f>_kronFlux : Flux from Kron Flux algorithm. Measured on <f>-band.
<f>_kronFluxErr : Uncertainty of <f>_kronFlux.
<f>_kronFlux_flag : Failure flag for <f>_kronFlux.
The Kron radius, <f>_kronRad
, is also available. In this case of LSST pipeline output, the Kron flux is not corrected for light that is emitted outside of the Kron aperture. While in many cases it will collect the majority of light, it will not be as accurate as the cModel for science cases requiring total flux.
Aperture fluxes¶
This contains the enclosed flux inside a given aperture (and not corrected to total fluxes using an aperture correction that accounts for the flux falling outside the aperture). Fixed aperture size refers to the aperture radius in pixels.
<f>_ap<pix>Flux : Flux within <pix>-pixel aperture. Forced on <f>-band.
<f>_ap<pix>FluxErr : Uncertainty of <f>_ap<pix>Flux.
<f>_ap<pix>FluxFlag : Failure flag for <f>_ap<pix>Flux.
The apertures are 3, 6, 9, 12, 17, 25, 35, 50, and 70 pixels. In the column name, apertures are 03
, 06
, 09
, 12
, and so on. While aperture fluxes are not corrected for the loss outside the aperture, if the aperture size is much larger than the galaxy size then it will approximate the total flux of the galaxy. The general application of these measurements are for measuring radial profiles (see Section 4 below).
4.1. Comparing total to apparent fluxes¶
This section will make several plots that compare the cModel
flux (which we take as the fiducial total flux, as commonly used for SDSS) to some of the apparent flux measurements. Kron, and aperture photometry are all measures of light within a fixed aperture.
Generally, magnitudes measured using aperture photometry in the LSST pipeline are fainter than those measured from cModel, because the fixed circular aperture systematically underestimates the flux in the galaxy wings (and the lost flux increases as the intrinsic size of the galaxy increases, e.g. as traced by the Kron radius).
First, compare cModel
to Kron
which should typically enclose 90% of the light.
fig, (ax, ax2) = plt.subplots(ncols=2, nrows=1,
width_ratios=[0.8, 0.2], figsize=(10, 6))
bins = np.arange(16, 27, 1)
ylims = [-1.2, 1.2]
ax.plot(cmodel_mag, (cmodel_mag - kron_mag), 's', alpha=.3,
label='cModel-Kron', color='blue')
x = cmodel_mag
y = (cmodel_mag-kron_mag)
bin_mean, bin_edge, binnum = binned_statistic(x, y,
statistic='median', bins=bins)
binctr = bin_edge[:-1] + (bin_edge[1:]-bin_edge[:-1]) / 2
ax.plot(binctr, bin_mean, color='k', lw=3, label=None, zorder=10)
ax.plot(binctr, bin_mean, color='blue', lw=2, label='bin median', zorder=11)
ax.plot(cmodel_mag, (cmodel_mag-sersic_mag), 'o', alpha=.3,
label='cModel - sersic', color='r')
x = cmodel_mag
y = (cmodel_mag-sersic_mag)
bin_mean, bin_edge, binnum = binned_statistic(x, y,
statistic='median', bins=bins)
binctr = bin_edge[:-1] + (bin_edge[1:]-bin_edge[:-1])/2
ax.plot(binctr, bin_mean, color='k', lw=3, label=None, zorder=10)
ax.plot(binctr, bin_mean, color='r', lw=2, label='bin median', zorder=11)
ax.axhline(0, linestyle='--')
ax.set_xlabel('cModel Magnitude')
ax.set_ylabel('cModel mag - sersic mag')
ax.set_ylim([-1, 1])
ax.legend()
ax2.hist((cmodel_mag-sersic_mag), orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 50), align='mid',
histtype="step", color='red', stacked=True, fill=False, label='Sersic')
ax2.hist((cmodel_mag-kron_mag), orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 50), align='mid',
histtype="step", color='blue', stacked=True, fill=False, label='Kron')
ax2.set_ylim(ylims)
ax2.axhline(0, linestyle='--', color='k')
ax.axhline(0, linestyle='--', color='k')
ax.set_xlabel('Kron Radius [i-band; pixels]')
ax.set_ylabel('cModel mag - Other mag')
ax.set_ylim(ylims)
ax.legend()
ax2.legend()
<matplotlib.legend.Legend at 0x7e861a2b1310>
Figure 3: A figure comparing the difference between cModel and Kron magnitudes, compared to the difference between cModel and sersic magnitudes (left panel). Generally, both Kron and sersic the measurements are in comparable agreement with cModel. The right panel shows the histogram of magnitude differences, demonstrating that there are not systematic offsets but slightly higher scatter from Kron with respect to cModel.
Below, explore how circular aperture photometry compares to cModel. Generally, magnitudes measured using aperture photometry in the LSST pipeline are fainter than those measured from cModel, because the fixed circular aperture systematically underestimates the flux in the galaxy wings (and the lost flux increases as the intrinsic size of the galaxy increases, e.g. as traced by the Kron radius).
fig, (ax, ax2) = plt.subplots(ncols=2, nrows=1,
width_ratios=[0.8, 0.2], figsize=(10, 6))
bins = np.arange(2, 15, 1)
ylims = [-1.5, 1.5]
ax.plot(i_kronRad, (cmodel_mag-ap06_mag), '^', alpha=.3,
label='6-pixel aperture', color='red')
ax.plot(i_kronRad, (cmodel_mag-ap09_mag), 's', alpha=.3,
label='9-pixel aperture', color='orange')
ax.plot(i_kronRad, (cmodel_mag-ap12_mag), 'o', alpha=.3,
label='12-pixel aperture', color='green')
ax.plot(i_kronRad, (cmodel_mag-ap17_mag), '.', alpha=.3,
label='17-pixel aperture', color='blue')
ax2.hist((cmodel_mag-ap17_mag), edgecolor='blue', orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 40), align='mid',
histtype="step", stacked=True, fill=False)
ax2.hist((cmodel_mag-ap12_mag), edgecolor='green', orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 40), align='mid',
histtype="step", stacked=True, fill=False)
ax2.hist((cmodel_mag-ap09_mag), edgecolor='orange', orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 40), align='mid',
histtype="step", stacked=True, fill=False)
ax2.hist((cmodel_mag-ap06_mag), edgecolor='red', orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 40), align='mid',
histtype="step", stacked=True, fill=False)
ax2.set_ylim(ylims)
ax.axhline(0, linestyle='--', color='k')
ax2.axhline(0, linestyle='--', color='k')
ax.set_xlabel('Kron Radius [i-band; pixels]')
ax.set_ylabel('cModel mag - Aperture mag')
ax.set_ylim(ylims)
ax.set_xlim([2, 12])
ax.legend()
<matplotlib.legend.Legend at 0x7e861a141760>
Figure 4: A comparison of the difference between cModel photometry and aperture photometry measured by the LSST pipelines for four different aperture sizes as a function of galaxy size (as measured using the Kron radius). The left panel shows the scatter plot of difference in photometry vs Kron radius, and the right panel shows a histogram of these values that demonstrate that larger aperture sizes have photometry that is closer to the cModel. The right panel shows histograms of the data in the left panel, where the colors indicate for the same data in each panel.
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(7, 6))
ylims = [-1.2, 1.2]
bins = np.arange(16, 27, 1)
ax.plot(cmodel_mag, (cmodel_mag-ap06_mag), '^', alpha=.1,
label='cModel 6-pix aperture', color='red')
x = cmodel_mag
y = (cmodel_mag-ap06_mag)
bin_mean, bin_edge, binnum = binned_statistic(x, y,
statistic='median', bins=bins)
binctr = bin_edge[:-1] + (bin_edge[1:]-bin_edge[:-1])/2
ax.plot(binctr, bin_mean, color='red', lw=2, label='bin median', zorder=10)
ax.plot(cmodel_mag, (cmodel_mag-ap09_mag), 's', alpha=.1,
label='cModel 9-pix aperture', color='orange')
x = cmodel_mag
y = (cmodel_mag-ap09_mag)
bin_mean, bin_edge, binnum = binned_statistic(x, y,
statistic='median', bins=bins)
binctr = bin_edge[:-1] + (bin_edge[1:]-bin_edge[:-1])/2
ax.plot(binctr, bin_mean, color='orange', lw=2,
label='bin median', zorder=10)
ax.plot(cmodel_mag, (cmodel_mag-ap12_mag), 'o', alpha=.1,
label='cModel 12-pix aperture', color='green')
x = cmodel_mag
y = (cmodel_mag-ap12_mag)
bin_mean, bin_edge, binnum = binned_statistic(x, y,
statistic='median', bins=bins)
binctr = bin_edge[:-1] + (bin_edge[1:]-bin_edge[:-1])/2
ax.plot(binctr, bin_mean, color='green', lw=2,
label='bin median', zorder=10)
ax.plot(cmodel_mag, (cmodel_mag-ap17_mag), '.', alpha=.1,
label='cModel 17-pix aperture', color='blue')
x = cmodel_mag
y = (cmodel_mag-ap17_mag)
bin_mean, bin_edge, binnum = binned_statistic(x, y,
statistic='median', bins=bins)
binctr = bin_edge[:-1] + (bin_edge[1:]-bin_edge[:-1])/2
ax.plot(binctr, bin_mean, color='blue', lw=2,
label='bin median', zorder=10)
ax.axhline(0, linestyle='--')
ax.set_xlabel('cModel Magnitude')
ax.set_ylabel('cModel mag - Aperture mag')
ax.set_ylim([-1, 1])
ax.set_xlim([20, 25])
ax.legend()
<matplotlib.legend.Legend at 0x7e861a1aff80>
Figure 5: A similar comparison of the difference between cModel photometry and aperture photometry measured by the LSST pipelines for four different aperture sizes, this time as a function of cModel magnitude. Running median is included.
These two figures show that the aperture photometry typically under-estimates the flux relative to the total flux estimated using cModel. As expected, there is a general trend for larger apertures to get closer to the total flux from cModel for large galaxies (i.e. whose Kron Radius is larger). There is also a general trend for the aperture photometry to be less discrepant at fainter magnitudes, since faint galaxies tend to be small.
4.2. Application of aperture photometry: radial profile¶
A science application for the aperture photometry is easy visualization of the radial profile of galaxies. In the cell below, make this plot for both a large galaxy (first) and a smaller galaxy of similar brightness (second). The query looks for bright galaxies whose cModel
magnitude ~ 20 ABmag. Dividing the aperture flux by the surface area of the aperture yields the surface brightness, which can be plotted as a function of radius from the center of the galaxy to compare radial light profiles.
wh = np.where((tab['i_kronRad'] > 20) & (cmodel_mag > 20)
& (cmodel_mag < 20.5))[0]
indx = 0
arcsec_per_pix = 0.2
rad = np.array([3, 6, 9, 12, 17, 25, 35, 50]) * arcsec_per_pix
area = np.pi * rad**2
profile = np.array([tab['i_ap03Flux'][wh][indx], tab['i_ap06Flux'][wh][indx],
tab['i_ap09Flux'][wh][indx], tab['i_ap12Flux'][wh][indx],
tab['i_ap17Flux'][wh][indx], tab['i_ap25Flux'][wh][indx],
tab['i_ap35Flux'][wh][indx],
tab['i_ap50Flux'][wh][indx]]) / area
plt.plot(rad, profile, linestyle=':',
label='Large Radius R='
+ str(np.round(i_kronRad[wh][indx]*arcsec_per_pix, 2)))
plt.xlabel('Aperture Radius [arcsec]')
plt.ylabel(r'Surface Brightness [nJy arcsec$^{-2}$]')
wh2 = np.where((tab['i_kronRad'] < 8) & (tab['i_kronRad'] > 5)
& (cmodel_mag > 20) & (cmodel_mag < 20.5))[0]
indx = 0
profile = np.array([tab['i_ap03Flux'][wh2][indx], tab['i_ap06Flux'][wh2][indx],
tab['i_ap09Flux'][wh2][indx], tab['i_ap12Flux'][wh2][indx],
tab['i_ap17Flux'][wh2][indx], tab['i_ap25Flux'][wh2][indx],
tab['i_ap35Flux'][wh2][indx],
tab['i_ap50Flux'][wh2][indx]])/area
plt.plot(rad, profile,
label='Small Radius R='
+ str(round(i_kronRad[wh2][indx]*arcsec_per_pix, 2)))
plt.legend()
plt.yscale('log')
Figure 6: Plot demonstrating the use of aperture photometry to plot the surface brightness profile (as a function of aperture radius) for a galaxy with large Kron radius (green solid) and small Kron radius (blue dotted).
5. Photometry for color¶
This section will explore GaaP fluxes (which are optimized for measuring accurate colors between bands).
GaaP fluxes¶
These are the Gaussian-aperture-and-PSF flux that is defined in Kuijken et al. 2008. The main goal of this method is to measure accurate colors while accounting for the different spatial resolution between filters. This is sometimes achieved in other datasets by convolving all images to the largest PSF, but this process of PSF-matching is computationally very time consuming for large images, thus motivating GaaP as a faster alternative. It is not a measure of total flux in a filter. Several measurement apertures are available.
Aperture
<f>_gaap<ap>Flux : GaaP flux with <ap> aperture after multiplying the seeing aperture. Forced on <f>-band.
<f>_gaap<ap>FluxErr : Uncertainty of <f>_gaap<ap>Flux.
Where the measurement apertures are 0.5, 0.7, 1.0, 1.5, 2.5, and 3.0 arcseconds. In the column name <ap>
appears as 0p5
, 0p7
, etc. Multiplying by the "seeing aperture" refers to convolving the PSF with a kernel so that the PSF is as if the seeing were 1.15 arcseconds. This has the effect of smearing the images of all filters consistently so that the colors are accurate.
For photometric redshifts, and other analysis where accurate colors are important, it is recommended to start with the GaaP fluxes with 1.0 aperture (optimal aperture was found to not perform as well, and should not be used). The largest aperture gaap3p0
might work better for larger galaxies, but gaap1p0
has better overall performance. Experiment yourself to see how it works for your science case.
5.1. Kron and GaaP comparison¶
In the next cell, compare the cModel instead to the Kron and GaaP measures.
fig, (ax, ax2) = plt.subplots(ncols=2, nrows=1,
width_ratios=[0.8, 0.2], figsize=(10, 6))
ylims = [-2, 2]
ax.plot(i_kronRad, (cmodel_mag-gaap_mag), 's', alpha=.3,
label='gaap1p0', color='orange')
ax.plot(i_kronRad, (cmodel_mag-kron_mag), 'o', alpha=.3,
label='Kron', color='blue')
ax2.hist((cmodel_mag-gaap_mag), orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 40), align='mid',
histtype="step", color='orange', stacked=True, fill=False, label='gaap1p0')
ax2.hist((cmodel_mag-kron_mag), orientation="horizontal",
bins=np.linspace(ylims[0], ylims[1], 40), align='mid',
histtype="step", color='blue', stacked=True, fill=False, label='Kron')
ax2.set_ylim(ylims)
ax.axhline(0, linestyle='--', color='k')
ax2.axhline(0, linestyle='--', color='k')
ax.set_xlabel('Kron Radius [i-band; pixels]')
ax.set_ylabel('cModel mag - Other mag')
ax.set_ylim(ylims)
ax.set_xlim([2, 15])
ax.legend()
ax2.legend()
<matplotlib.legend.Legend at 0x7e861a035dc0>
Figure 7: The left panel figure shows the i-band magnitude difference between cModel and Kron (orange circles) and between cModel and gaap1p0 (blue squares) vs the Kron radius (a proxy for galaxy size) for the galaxies in the query. The dashed line indicates where the two magnitudes would have the same value. The gaap1p0 magnitude always underestimates the flux, but the offset becomes worse for larger galaxies (relative to the fixed aperture). The right panel shows the histogram of the magnitude differences in the left panel, illustrating that while cModel - Kron magnitudes are similar on average (blue histogram) the gaap1p0 systematically underestimates the flux relative to cModel (orange histogram).
5.2. CMD with GaaP¶
This section demonstrates using GaaP photometry to calculate accurate galaxy colors to identify different types of galaxies. First, define magnitudes from g, r, and i band photometry. The second cell will then compare the colors of galaxies that overlap the galaxy cluster with that in the field. In clusters, galaxies tend to be old, red elliptical galaxies and thus exhibit a well defined red sequence in color space.
The earlier query in Section 2 returned galaxies from a blank, "field" location (the ECDFS). These will be dominated by bluer star forming galaxies which are most common in field environments.
Below, add a new query near a known galaxy cluster at redshift z=0.3. This is Abell 360 and sits in the DP1 data from the low ecliptic latitude field.
cluster_ra = 37.83
cluster_dec = 6.98
query = "SELECT obj.objectId, obj.coord_ra, obj.coord_dec, " + \
"obj.detect_fromBlend, obj.detect_isIsolated, " + \
"obj.i_blendedness, obj.i_extendedness, " + \
"obj.i_kronFlux, obj.i_kronFluxErr, obj.i_kronRad, " + \
"obj.i_cModelFlux, obj.i_cModelFluxErr, obj.i_gaap1p0Flux, obj.i_gaap3p0Flux, " + \
"obj.g_gaap1p0Flux, obj.g_gaap3p0Flux, " + \
"obj.i_kronFlux_flag, obj.i_cModel_flag " + \
"FROM dp1.Object AS obj " + \
"WHERE (obj.i_cModelFlux/obj.i_cModelFluxErr > 20) AND " + \
"(obj.i_extendedness = 1) AND " + \
"(obj.i_kronFlux_flag = 0) AND (obj.i_cModel_flag = 0) AND " + \
"CONTAINS(POINT('ICRS', obj.coord_ra, obj.coord_dec), " + \
"CIRCLE('ICRS',"+str(cluster_ra)+","+str(cluster_dec)+", 0.2)) = 1 "
job = service.submit_job(query)
job.run()
job.wait(phases=['COMPLETED', 'ERROR'])
print('Job phase is', job.phase)
Job phase is COMPLETED
if job.phase == 'ERROR':
job.raise_if_error()
assert job.phase == 'COMPLETED'
results = job.fetch_result()
tab2 = results.to_table()
First, calculate the magnitudes of galaxies in the 'field' location. Then, calculate the magnitudes for the other filters near the galaxy cluster from the query performed in the cell above. This will enable plotting their colors.
Warning: Like in Section 2, the following cell will produce warnings for invalid value encountered in log10, which happens if the source flux is negative. This happens for a small number of objects and since the goal of the plot is to see the distribution of the majority of sources, the warning can be safely ignored.
g_field_gaap_mag = -2.50 * np.log10(tab['g_gaap1p0Flux']) + 31.4
i_field_gaap_mag = -2.50 * np.log10(tab['i_gaap1p0Flux']) + 31.4
i_field_cmodel_mag = -2.50 * np.log10(tab['i_cModelFlux']) + 31.4
i_cluster_gaap_mag = -2.50 * np.log10(tab2['i_gaap1p0Flux']) + 31.4
g_cluster_gaap_mag = -2.50 * np.log10(tab2['g_gaap1p0Flux']) + 31.4
i_cluster_cmodel_mag = -2.50 * np.log10(tab2['i_cModelFlux']) + 31.4
/tmp/ipykernel_66304/3627765783.py:5: RuntimeWarning: invalid value encountered in log10 g_cluster_gaap_mag = -2.50 * np.log10(tab2['g_gaap1p0Flux']) + 31.4
fig, (ax, ax1) = plt.subplots(ncols=1, nrows=2, figsize=(10, 6))
ax.plot(i_field_cmodel_mag, (g_field_gaap_mag-i_field_gaap_mag),
'.', alpha=.1, color='blue', label='Field Galaxies (ECDFS)')
ax.set_xlabel('i-band Magnitude [cModel]')
ax.set_ylabel('g-i color')
ax.set_ylim([-1, 4])
ax.legend()
ax1.plot(i_cluster_cmodel_mag, (g_cluster_gaap_mag-i_cluster_gaap_mag),
'.', alpha=.1, color='r', label='Cluster Galaxies (Abell 360)')
ax1.set_xlabel('i-band Magnitude [cModel]')
ax1.set_ylabel('g-i color')
ax1.set_ylim([-1, 4])
ax1.legend()
<matplotlib.legend.Legend at 0x7e8619e71b80>
Figure 8: The g − i vs. i color-magnitude diagram for galaxies selected in the queries. Top panel shows the galaxies selected from in a random field that does not contain a galaxy cluster (ECDFS). The bottom panel shows galaxies from a field with a galaxy cluster (A360). The cluster galaxies appear as a "red sequence" with red i-g colors, because the Balmer / 4000 Angstrom break spectral feature that traces older stars sits between the bands.
A very nice red sequence appears from the red, old galaxies in the cluster!
6. Exercise for the learner¶
Compare the <f>_free_cModelFlux
measurements to <f>_cModelFlux
in the filters that are not the reference band where the <f>_cModelFlux
was measured (i.e. refBand
). Investigate how leaving the cModel measurements free differs from the one measured with parameters fixed to the refBand
, as a function of decreasing signal to noise. As an additional exercise, check how the signal to noise in colors measured using <f>_gaap1p0Flux
values compare to those measured with the larger 3.0" aperture, <f>_gaap3p0Flux
, where the larger aperture may increase the noise.