diff --git a/notebooks/psf_photometry/NIRCam_PSF_Photometry_Example.ipynb b/notebooks/psf_photometry/NIRCam_PSF_Photometry_Example.ipynb index 2afd8b07b..01a3ccc27 100644 --- a/notebooks/psf_photometry/NIRCam_PSF_Photometry_Example.ipynb +++ b/notebooks/psf_photometry/NIRCam_PSF_Photometry_Example.ipynb @@ -72,8 +72,8 @@ "os.environ[\"PYSYN_CDBS\"] = \"./grp/redcat/trds/\"\n", "\n", "# WEBBPSF Data\n", - "boxlink = 'https://stsci.box.com/shared/static/34o0keicz2iujyilg4uz617va46ks6u9.gz' \n", - "boxfile = './webbpsf-data/webbpsf-data-1.0.0.tar.gz'\n", + "boxlink = 'https://stsci.box.com/shared/static/qxpiaxsjwo15ml6m4pkhtk36c9jgj70k.gz'\n", + "boxfile = './webbpsf-data/webbpsf-data-1.2.1.tar.gz'\n", "synphot_url = 'http://ssb.stsci.edu/trds/tarfiles/synphot5.tar.gz'\n", "synphot_file = './synphot5.tar.gz'\n", "\n", @@ -94,8 +94,7 @@ " os.makedirs(synphot_folder)\n", " urllib.request.urlretrieve(synphot_url, synphot_file)\n", " gzf = tarfile.open(synphot_file)\n", - " gzf.extractall('./')\n", - "\n" + " gzf.extractall('./')" ] }, { @@ -111,46 +110,39 @@ "metadata": {}, "outputs": [], "source": [ + "import glob as glob\n", "import os\n", "import sys\n", + "import tarfile\n", "import time\n", + "import urllib.request\n", "\n", + "import jwst\n", "import numpy as np\n", - "\n", "import pandas as pd\n", - "\n", - "import glob as glob\n", - "\n", - "import jwst\n", - "from jwst.datamodels import ImageModel\n", - "\n", - "import tarfile\n", - "\n", - "import urllib.request\n", - "\n", - "from astropy import wcs\n", + "import webbpsf\n", "from astropy import units as u\n", + "from astropy import wcs\n", + "from astropy.coordinates import SkyCoord, match_coordinates_sky\n", "from astropy.io import fits\n", - "from astropy.visualization import (ZScaleInterval, SqrtStretch, ImageNormalize)\n", - "from astropy.visualization import simple_norm\n", - "from astropy.nddata import Cutout2D, NDData\n", - "from astropy.stats import gaussian_sigma_to_fwhm\n", - "from astropy.table import Table, QTable\n", "from astropy.modeling.fitting import LevMarLSQFitter\n", + "from astropy.nddata import Cutout2D, NDData\n", + "from astropy.stats import gaussian_sigma_to_fwhm, sigma_clipped_stats\n", + "from astropy.table import QTable, Table\n", + "from astropy.visualization import (ImageNormalize, SqrtStretch, ZScaleInterval,\n", + " simple_norm)\n", "from astropy.wcs.utils import pixel_to_skycoord\n", - "from astropy.coordinates import SkyCoord, match_coordinates_sky\n", - "from astropy.stats import sigma_clipped_stats\n", - "\n", - "from photutils import CircularAperture, EPSFBuilder, find_peaks, CircularAnnulus\n", - "from photutils.detection import DAOStarFinder, IRAFStarFinder\n", - "from photutils.psf import DAOGroup, IntegratedGaussianPRF, extract_stars, IterativelySubtractedPSFPhotometry\n", - "from photutils.background import MMMBackground, MADStdBackgroundRMS\n", - "from photutils.centroids import centroid_2dg\n", - "from photutils import aperture_photometry\n", - "\n", "from ipywidgets import interact\n", - "\n", - "import webbpsf\n", + "from jwst.datamodels import ImageModel\n", + "from photutils.aperture import (CircularAnnulus, CircularAperture,\n", + " aperture_photometry)\n", + "from photutils.background import MADStdBackgroundRMS, MMMBackground\n", + "from photutils.centroids import centroid_2dg\n", + "from photutils.detection import DAOStarFinder, IRAFStarFinder, find_peaks\n", + "from photutils.psf import (DAOGroup, EPSFBuilder, IntegratedGaussianPRF,\n", + " IterativelySubtractedPSFPhotometry,\n", + " IterativePSFPhotometry, SourceGrouper,\n", + " extract_stars)\n", "from webbpsf.utils import to_griddedpsfmodel" ] }, @@ -252,7 +244,7 @@ " else:\n", " d = d\n", "\n", - " wv = np.float(f[1:3])\n", + " wv = float(f[1:3])\n", "\n", " if wv > 24: \n", " ff_long.append(f)\n", @@ -600,15 +592,10 @@ ] }, { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Developer Note: Currently, display_psf_grid has a bug which has been fixed, but will not merged into the latest WebbPSF release until after commissioning. We have turned off this cell for the time being." - ] - }, - { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "webbpsf.gridded_library.display_psf_grid(dict_psfs_webbpsf[dets_short[0]][filts_short[0]]['psf model grid'],\n", " zoom_in=False, figsize=(14, 14))" @@ -620,7 +607,7 @@ "source": [ "## II. Create the PSF model building an Effective PSF (ePSF)\n", "\n", - "More information on the PhotUtils Effective PSF can be found [here](https://photutils.readthedocs.io/en/stable/epsf.html).\n", + "More information on the photutils Effective PSF can be found [here](https://photutils.readthedocs.io/en/stable/epsf.html).\n", "\n", "* Select the stars from the images we want to use for building the PSF. We use the [DAOStarFinder](https://photutils.readthedocs.io/en/stable/api/photutils.detection.DAOStarFinder.html) function to find bright stars in the images (setting a high detection threshold). [DAOStarFinder](https://photutils.readthedocs.io/en/stable/api/photutils.detection.DAOStarFinder.html#photutils.detection.DAOStarFinder) detects stars in an image using the DAOFIND ([Stetson 1987](https://ui.adsabs.harvard.edu/abs/1987PASP...99..191S/abstract)) algorithm. DAOFIND searches images for local density maxima that have a peak amplitude greater than `threshold` (approximately; threshold is applied to a convolved image) and have a size and shape similar to the defined 2D Gaussian kernel. \\\n", " **Note**: The threshold and the maximum distance to the closest neighbour depend on the user science case (i.e.; number of stars in the field of view, crowding, number of bright sources, minimum number of stars required to build the ePSF, etc.) and must be modified accordingly. \n", @@ -1005,7 +992,6 @@ " dict_phot[det][filt]['output photometry tables'] = {}\n", "\n", " for i in np.arange(0, len(dict_images[det][filt]['images']), 1):\n", - "\n", " dict_phot[det][filt]['residual images'][i + 1] = None\n", " dict_phot[det][filt]['output photometry tables'][i + 1] = None" ] @@ -1055,7 +1041,7 @@ " daofind = DAOStarFinder(threshold=th * std + bkg, fwhm=sigma_psf, roundhi=1.0, roundlo=-1.0,\n", " sharplo=0.30, sharphi=1.40)\n", " \n", - " daogroup = DAOGroup(5.0 * sigma_psf)\n", + " grouper = SourceGrouper(5.0 * sigma_psf)\n", " \n", " # grid PSF\n", "\n", @@ -1078,19 +1064,21 @@ " print(\"Performing the photometry on image {number} of filter {f}, detector {d}\".format(number=i + 1, f=filt, d=det))\n", " \n", " tic = time.perf_counter()\n", + "\n", + " data_sub = data - mmm_bkg(data)\n", + " psf_shape = (11, 11)\n", " \n", - " phot = IterativelySubtractedPSFPhotometry(finder=daofind, group_maker=daogroup,\n", - " bkg_estimator=mmm_bkg, psf_model=psf_model,\n", - " fitter=LevMarLSQFitter(),\n", - " niters=2, fitshape=(11, 11), aperture_radius=ap_radius[j])\n", - " result = phot(data)\n", + " phot = IterativePSFPhotometry(psf_model, psf_shape, daofind,\n", + " grouper=grouper, fitter=LevMarLSQFitter(),\n", + " maxiters=2, aperture_radius=ap_radius[j])\n", + " result = phot(data_sub)\n", " \n", " toc = time.perf_counter()\n", " \n", " print(\"Time needed to perform photometry on image {number}:\".format(number=i + 1), \"%.2f\" % ((toc - tic) / 3600), \"hours\")\n", " print(\"Number of sources detected in image {number} for filter {f}:\".format(number=i + 1, f=filt), len(result))\n", " \n", - " residual_image = phot.get_residual_image()\n", + " residual_image = phot.make_residual_image(data_sub, psf_shape)\n", " \n", " dict_phot[det][filt]['residual images'][i + 1] = residual_image\n", " dict_phot[det][filt]['output photometry tables'][i + 1] = result\n", @@ -1145,12 +1133,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Output Photometry Table\n", - "\n", - "\n", - "### Note for developer: \n", - "\n", - "It would be really useful, if PhotUtils can provide some diagnostics to identify the quality of the photometry in the final catalog for each source (similarly to all the other PSF photometry programs available)." + "## Output Photometry Table" ] }, { @@ -1922,7 +1905,7 @@ " else:\n", " d = d\n", "\n", - " wv = np.float(f[1:3])\n", + " wv = float(f[1:3])\n", "\n", " if wv > 24:\n", " ff_long.append(f)\n", @@ -2718,7 +2701,7 @@ "source": [ "## Final notes\n", "\n", - "This notebook provides a general overview on how to perform PSF photometry using the [PhotUtils](https://photutils.readthedocs.io/en/stable/) package. The choice of the different parameters adopted in all the reduction steps as well as the choice of the PSF model depend on the specific user science case. Moreover, a detailed analysis that allow to provide recommendations on how to set those parameters and outline the differences in the output photometry when different PSF models are adopted (single vs PSF grid, number of PSFs in the grid, etc.) will be possible only when real data will be available after the instrument commissioning. In this context, we note that one of the selected ERS program (ERS 1334 - The Resolved Stellar Populations Early Release Science Program) will provide a fundamental test benchmark to explore how the different choices outlined above will impact the quality of the PSF photometry in a crowded stellar region." + "This notebook provides a general overview on how to perform PSF photometry using the [photutils](https://photutils.readthedocs.io/en/stable/) package. The choice of the different parameters adopted in all the reduction steps as well as the choice of the PSF model depend on the specific user science case. Moreover, a detailed analysis that allow to provide recommendations on how to set those parameters and outline the differences in the output photometry when different PSF models are adopted (single vs PSF grid, number of PSFs in the grid, etc.) will be possible only when real data will be available after the instrument commissioning. In this context, we note that one of the selected ERS program (ERS 1334 - The Resolved Stellar Populations Early Release Science Program) will provide a fundamental test benchmark to explore how the different choices outlined above will impact the quality of the PSF photometry in a crowded stellar region." ] }, { @@ -2757,7 +2740,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.10" + "version": "3.11.5" } }, "nbformat": 4, diff --git a/notebooks/psf_photometry/requirements.txt b/notebooks/psf_photometry/requirements.txt index ef0875748..dc69fd6f6 100644 --- a/notebooks/psf_photometry/requirements.txt +++ b/notebooks/psf_photometry/requirements.txt @@ -1,9 +1,9 @@ -numpy>=1.22.4 -pandas>=1.4.2 -jwst==1.5.2 -astropy>=5.1 -photutils==1.4.0 -ipywidgets>=7.7.0 -webbpsf>=1.0.0 -matplotlib>=3.5.2 -stsynphot==1.1.0 +numpy>=1.25.2 +pandas>=2.1.0 +jwst>=1.11.4 +astropy>=5.3.3 +photutils>=1.9.0 +ipywidgets>=8.1.1 +matplotlib>=3.7.2 +webbpsf>=1.2.1 +stsynphot>=1.2.0