Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 43 additions & 89 deletions DP2/300_Science_demos/303_Galaxies/303_1_Galaxy_photometry.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
"\n",
"</div>\n",
"\n",
"For the Rubin Science Platform at data.lsst.cloud. <br>\n",
"Data Release: <a href=\"https://dp2.lsst.io/\">Data Preview 2</a> <br>\n",
"Container Size: large <br>\n",
"LSST Science Pipelines version: r30.0.10 <br>\n",
"Last verified to run: 2026-08-28 <br>\n",
"Repository: <a href=\"https://github.com/lsst/tutorial-notebooks\">github.com/lsst/tutorial-notebooks</a> <br>"
"For the Rubin Science Platform at data.lsst.cloud.\\\n",
"Data Release: [Data Preview 2](https://dp2.lsst.io/)\\\n",
"Container Size: Large\\\n",
"LSST Science Pipelines version: r30.0.11\\\n",
"Last verified to run: 2026-09-04\\\n",
"Repository: [github.com/lsst/tutorial-notebooks](https://github.com/lsst/tutorial-notebooks)\\\n",
"DOI: [10.11578/rubin/dc.20250909.20](https://doi.org/10.11578/rubin/dc.20250909.20)"
]
},
{
Expand Down Expand Up @@ -90,9 +91,7 @@
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"from lsst.rsp import RSPDiscovery\n",
"\n",
"from scipy.stats import binned_statistic"
]
},
Expand Down Expand Up @@ -120,9 +119,7 @@
"outputs": [],
"source": [
"discovery = RSPDiscovery(\"dp2\")\n",
"service = discovery.get_tap_client()\n",
"\n",
"assert service is not None"
"service = discovery.get_tap_client()"
]
},
{
Expand All @@ -133,11 +130,12 @@
"## 2. Types of photometry\n",
"\n",
"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. \n",
"\n",
"### 2.1. Explore the schema\n",
"\n",
"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. \n",
"\n",
"Schema for the object catalog for DP2 <a href=\"https://sdm-schemas.lsst.io/dp2.html\">is available here</a>. It lists the catalog header and brief explanation of the parameters."
"Descriptions for all the measurements in the `object` table can be found in the [DP2 schema](https://sdm-schemas.lsst.io/dp2.html); the schema can also be obtained programmatically as demonstrated in the following code cells."
]
},
{
Expand All @@ -158,7 +156,6 @@
"query = \"SELECT column_name, datatype, description, unit \" \\\n",
" \"FROM tap_schema.columns \" \\\n",
" \"WHERE table_name = 'dp2.Object'\"\n",
"\n",
"results = service.search(query).to_table()"
]
},
Expand All @@ -176,7 +173,6 @@
"for cname in results['column_name']:\n",
" if cname.find(search_string) > -1 and cname.find(band) > -1 and \\\n",
" cname.find(exclude1) == -1 and cname.find(exclude2) == -1:\n",
"\n",
" print(cname)"
]
},
Expand Down Expand Up @@ -212,31 +208,24 @@
"source": [
"### 2.2. Select a galaxy sample\n",
"\n",
"Below, query the DP2 `object` table for a selection of photometric measurements. \n",
"Query the DP2 `object` table for a selection of photometric measurements. \n",
"\n",
"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).\n",
"Limit the search to contain galaxies using the `i_extendedness` flag. This will exclude many point-like objects, but not all. While some contamination by point-like objects is tolerable for the purposes of this demonstration, users should consider the variety of extendedness measurements when deciding how to constrain samples for scientific analysis (see, e.g., the [flag usage guidance](https://dp2.lsst.io/products/flags/index.html)). \n",
"\n",
"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).\n",
"\n",
"Search for the sample using the DP2 imaging obtained in the Extended Chandra Deep Field South (ECDFS; center ra, dec = 53.2, -28.1 in degrees)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "73dd5a5f-b761-4d4f-96b6-5767cffbb310",
"metadata": {},
"outputs": [],
"source": [
"target_ra = 53.2\n",
"target_dec = -28.1"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "75150971-e118-48d5-9db7-74c0fe600762",
"metadata": {},
"outputs": [],
"source": [
"target_ra = 53.2\n",
"target_dec = -28.1\n",
"query = \"SELECT obj.objectId, obj.coord_ra, obj.coord_dec, \" + \\\n",
" \"obj.detect_fromBlend, obj.detect_isIsolated, \" + \\\n",
" \"obj.i_blendedness, obj.i_extendedness, \" + \\\n",
Expand Down Expand Up @@ -268,19 +257,11 @@
"job = service.submit_job(query)\n",
"job.run()\n",
"job.wait(phases=['COMPLETED', 'ERROR'])\n",
"print('Job phase is', job.phase)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5b6cd0ba-132a-4552-b389-32e54d8591dc",
"metadata": {},
"outputs": [],
"source": [
"print('Job phase is', job.phase)\n",
"if job.phase == 'ERROR':\n",
" job.raise_if_error()\n",
"assert job.phase == 'COMPLETED'"
"assert job.phase == 'COMPLETED'\n",
"tab = job.fetch_result().to_table()"
]
},
{
Expand All @@ -298,8 +279,6 @@
"metadata": {},
"outputs": [],
"source": [
"results = job.fetch_result()\n",
"tab = results.to_table()\n",
"tab"
]
},
Expand Down Expand Up @@ -345,7 +324,7 @@
"\n",
"##### Sersic fluxes\n",
"\n",
"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 <a href=\"https://en.wikipedia.org/wiki/S%C3%A9rsic_profile\">is available here</a>.\n",
"This photometric measurement models all galaxies as a single Sersic profile and calculates its total flux according to the best fitting model. See the [Sersic profile Wikipedia page](https://en.wikipedia.org/wiki/S%C3%A9rsic_profile) for more information.\n",
"\n",
"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. \n",
"\n",
Expand All @@ -355,12 +334,12 @@
"sersic_no_data_flag : Failure flag for <f>_sersicFlux\n",
"```\n",
"\n",
"The LSST pipeline package responsible for `Sersic` fluxes is called `multiprofit` and documentation is <a href=\"https://pipelines.lsst.io/modules/lsst.multiprofit/index.html#module-lsst.multiprofit\">available here</a>.\n",
"The LSST pipeline package responsible for `Sersic` fluxes is called `multiprofit`. [Visit the multiprofit documentation](https://pipelines.lsst.io/modules/lsst.multiprofit/index.html#module-lsst.multiprofit).\n",
"\n",
"\n",
"##### Exponential fluxes\n",
"\n",
"This photometric measurement models all galaxies as a single Sersic profile with Sersic index n fixed to 1 (exponential disk) and calculates its total flux according to the best fitting model. More information the Sersic profile <a href=\"https://en.wikipedia.org/wiki/S%C3%A9rsic_profile\">is available here</a>.\n",
"This photometric measurement models all galaxies as a single Sersic profile with Sersic index n fixed to 1 (exponential disk) and calculates its total flux according to the best fitting model. See the [Sersic profile Wikipedia page](https://en.wikipedia.org/wiki/S%C3%A9rsic_profile) for more information.\n",
"\n",
"The best fit exponential 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 when n is fixed to 1. \n",
"\n",
Expand All @@ -369,11 +348,9 @@
"<f>_exponentialFluxErr : Uncertainty of <f>_exponentialFlux\n",
"```\n",
"\n",
" \n",
"\n",
"##### Composite Model (CModel) fluxes\n",
"\n",
"Similar in nature to those measured for SDSS (information <a href=\"https://www.sdss3.org/dr8/algorithms/magnitudes.php#cmodel\">available here</a>) that will be familiar to SDSS users. \n",
"Similar in nature to the [SDSS cModel photometry](https://www.sdss3.org/dr8/algorithms/magnitudes.php#cmodel), these will be familiar to SDSS users. \n",
"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 exponential fluxes that assume either a disk (n=1) or a bulge (n=4).\n",
"\n",
"```\n",
Expand Down Expand Up @@ -403,7 +380,7 @@
"```\n",
"<f>_cModel_devFlux : Flux from the cmodel fit with n=4. Forced on <f>-band.\n",
"<f>_cModel_devFluxErr : Uncertainty of <f>_cModel_devFlux\n",
"```\n"
"```"
]
},
{
Expand All @@ -421,8 +398,8 @@
"metadata": {},
"outputs": [],
"source": [
"tab['i_bdFluxB'] = tab['i_cModelFlux']*tab['i_cModel_fracDev']\n",
"tab['i_bdFluxD'] = tab['i_cModelFlux']* (1 - tab['i_cModel_fracDev'])\n",
"tab['i_bdFluxB'] = tab['i_cModelFlux'] * tab['i_cModel_fracDev']\n",
"tab['i_bdFluxD'] = tab['i_cModelFlux'] * (1 - tab['i_cModel_fracDev'])\n",
"bdFluxD_mag = -2.50 * np.log10(tab['i_bdFluxD']) + 31.4\n",
"bdFluxB_mag = -2.50 * np.log10(tab['i_bdFluxB']) + 31.4"
]
Expand Down Expand Up @@ -525,7 +502,7 @@
"id": "ebf6c3b5-915a-44b9-8557-d2ae26d239ef",
"metadata": {},
"source": [
"### 3.2 Exponential disk fluxes\n",
"### 3.2. Exponential disk fluxes\n",
"\n",
"Two estimates of total flux based on modeling objects as exponential disks (Sersic model with Sersic index n = 1) are in the `object` table. They are calculated using different algorithms, but the plot below demonstrates that the fluxes are very similar."
]
Expand All @@ -539,11 +516,11 @@
"source": [
"fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(8, 6))\n",
"\n",
"one2one = np.arange(0,35000,1)\n",
"one2one = np.arange(0, 35000, 1)\n",
"\n",
"ax.plot(tab['i_exponentialFlux'], tab['i_cModel_expFlux'], 'o', alpha=.3)\n",
"\n",
"ax.plot(one2one,one2one,linestyle='--',color='k',label='1:1')\n",
"ax.plot(one2one, one2one, linestyle='--', color='k', label='1:1')\n",
"ax.set_xlabel('i_exponentialFlux')\n",
"ax.set_ylabel('i_cModel_expFlux')\n",
"plt.legend()"
Expand Down Expand Up @@ -573,7 +550,7 @@
"outputs": [],
"source": [
"plt.plot(tab['i_cModelFlux'], tab['i_bdFluxB'] + tab['i_bdFluxD'], '.', alpha=.3,\n",
" color='blue')\n",
" color='blue')\n",
"\n",
"plt.xlabel('i_cModelFlux')\n",
"plt.ylabel('cModel Bulge + Disk components')"
Expand Down Expand Up @@ -957,8 +934,7 @@
"profile = np.array([tab['i_ap03Flux'][wh][indx], tab['i_ap06Flux'][wh][indx],\n",
" tab['i_ap09Flux'][wh][indx], tab['i_ap12Flux'][wh][indx],\n",
" tab['i_ap17Flux'][wh][indx], tab['i_ap25Flux'][wh][indx],\n",
" tab['i_ap35Flux'][wh][indx],\n",
" tab['i_ap50Flux'][wh][indx]]) / area\n",
" tab['i_ap35Flux'][wh][indx], tab['i_ap50Flux'][wh][indx]]) / area\n",
"\n",
"plt.plot(rad, profile, linestyle=':',\n",
" label='Large Radius R='\n",
Expand All @@ -970,13 +946,12 @@
" & (cmodel_mag > 20) & (cmodel_mag < 21.5))[0]\n",
"\n",
"indx = 0\n",
"print(\"large galaxy mag = \",cmodel_mag[wh][indx],\" small galaxy mag = \",cmodel_mag[wh2][indx])\n",
"print(\"large galaxy mag = \", cmodel_mag[wh][indx], \" small galaxy mag = \", cmodel_mag[wh2][indx])\n",
"\n",
"profile = np.array([tab['i_ap03Flux'][wh2][indx], tab['i_ap06Flux'][wh2][indx],\n",
" tab['i_ap09Flux'][wh2][indx], tab['i_ap12Flux'][wh2][indx],\n",
" tab['i_ap17Flux'][wh2][indx], tab['i_ap25Flux'][wh2][indx],\n",
" tab['i_ap35Flux'][wh2][indx],\n",
" tab['i_ap50Flux'][wh2][indx]])/area\n",
" tab['i_ap35Flux'][wh2][indx], tab['i_ap50Flux'][wh2][indx]])/area\n",
"\n",
"plt.plot(rad, profile,\n",
" label='Small Radius R='\n",
Expand Down Expand Up @@ -1080,11 +1055,11 @@
"source": [
"#### 5.2. CMD with GaaP\n",
"\n",
"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. \n",
"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, 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. \n",
"\n",
"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.\n",
"The earlier query in Section 2 returned signal-to-noise ratio $>20$ galaxies from a blank, \"field\" location (the ECDFS) and stored them in the `tab` table. These will be dominated by bluer star forming galaxies which are most common in field environments.\n",
"\n",
"Below, add a new query near a known galaxy cluster PSZ2 G309.43-72.86 at redshift z=0.35. \n"
"Add a new query near a known galaxy cluster PSZ2 G309.43-72.86 at redshift z=0.35, from the ELAIS-S1 field, and use a signal-to-noise ratio $>50$ instead of $20$."
]
},
{
Expand All @@ -1096,8 +1071,6 @@
"source": [
"cluster_ra = 10.2082\n",
"cluster_dec = -44.1307\n",
"\n",
"\n",
"query = \"SELECT obj.objectId, obj.coord_ra, obj.coord_dec, \" + \\\n",
" \"obj.detect_fromBlend, obj.detect_isIsolated, \" + \\\n",
" \"obj.i_blendedness, obj.i_extendedness, \" + \\\n",
Expand All @@ -1110,7 +1083,7 @@
" \"(obj.i_extendedness = 1) AND \" + \\\n",
" \"(obj.i_kronFlux_flag = 0) AND (obj.i_cModel_flag = 0) AND \" + \\\n",
" \"CONTAINS(POINT('ICRS', obj.coord_ra, obj.coord_dec), \" + \\\n",
" \"CIRCLE('ICRS',\"+str(cluster_ra)+\",\"+str(cluster_dec)+\", 0.2)) = 1 \"\n"
" \"CIRCLE('ICRS',\"+str(cluster_ra)+\",\"+str(cluster_dec)+\", 0.2)) = 1 \""
]
},
{
Expand All @@ -1123,30 +1096,11 @@
"job = service.submit_job(query)\n",
"job.run()\n",
"job.wait(phases=['COMPLETED', 'ERROR'])\n",
"print('Job phase is', job.phase)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "18bc593d-bf80-44c1-9a33-158606fa2c8c",
"metadata": {},
"outputs": [],
"source": [
"print('Job phase is', job.phase)\n",
"if job.phase == 'ERROR':\n",
" job.raise_if_error()\n",
"assert job.phase == 'COMPLETED'"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "32400242-e8f6-4461-941a-8617f75960de",
"metadata": {},
"outputs": [],
"source": [
"results = job.fetch_result()\n",
"tab2 = results.to_table()"
"assert job.phase == 'COMPLETED'\n",
"tab2 = job.fetch_result().to_table()"
]
},
{
Expand Down Expand Up @@ -1181,7 +1135,7 @@
"metadata": {},
"outputs": [],
"source": [
"fig, (ax, ax1) = plt.subplots(ncols=1, nrows=2, figsize=(10, 6))\n",
"fig, (ax, ax1) = plt.subplots(ncols=1, nrows=2, figsize=(10, 6), sharex=True)\n",
"\n",
"ax.plot(i_field_cmodel_mag, (r_field_gaap_mag-i_field_gaap_mag),\n",
" '.', alpha=.1, color='blue', label='Field Galaxies (ECDFS)')\n",
Expand All @@ -1191,7 +1145,7 @@
"ax.legend()\n",
"\n",
"ax1.plot(i_cluster_cmodel_mag, (r_cluster_gaap_mag-i_cluster_gaap_mag),\n",
" '.', alpha=.1, color='r', label='Cluster Galaxies (PSZ2 G309.43-72.86)')\n",
" '.', alpha=.1, color='r', label='Cluster Galaxies (PSZ2 G309.43-72.86; ELAIS-S1)')\n",
"ax1.set_xlabel('i-band Magnitude [cModel]')\n",
"ax1.set_ylabel('r-i color')\n",
"ax1.set_ylim([-1, 2])\n",
Expand All @@ -1203,7 +1157,7 @@
"id": "b4e3745a-8e04-4243-898c-10c8d25aae4b",
"metadata": {},
"source": [
"> **Figure 10:** The r − 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, PSZ2 G309.43-72.86. The cluster galaxies appear as a \"red sequence\" with red r-i colors, because the Balmer / 4000 Angstrom break spectral feature that traces older stars sits between the bands."
"> **Figure 10:** The r − i vs. i color-magnitude diagram for galaxies selected in the queries. Top panel shows the SNR$>20$ galaxies selected from in a random field that does not contain a galaxy cluster (ECDFS). The bottom panel shows the SNR$>50$ galaxies from a field with a galaxy cluster, PSZ2 G309.43-72.86. The cluster galaxies appear as a \"red sequence\" with red r-i colors, because the Balmer / 4000 Angstrom break spectral feature that traces older stars sits between the bands. The faint-end cutoff is different for the two subsets due to the different SNR used in the query selection."
]
},
{
Expand Down
Loading
Loading