diff --git a/notebooks/concepts/generate_mosviz_photometry.ipynb b/notebooks/concepts/generate_mosviz_photometry.ipynb index dddd6bd18a..91925d932c 100644 --- a/notebooks/concepts/generate_mosviz_photometry.ipynb +++ b/notebooks/concepts/generate_mosviz_photometry.ipynb @@ -27,6 +27,8 @@ "source": [ "### Import packages\n", "\n", + "- `os` helps us create a new directory for the final cutouts from the synthetic image.\n", + "- `glob.glob` lists local files that match a given pattern.\n", "- We use `astropy.units` to convert between degrees and arcseconds.\n", "- `astropy.coordinates.SkyCoord` helps merge lists of right ascensions (RA) and declinations (Dec) into one object.\n", "- `astropy.convolution.Gaussian2DKernel` smooths two-dimensional data by performing convolutions with two Gaussian functions.\n", @@ -34,13 +36,14 @@ "- The objects from `astropy.nddata` assist in creating cutouts once we have identified galaxies to take from the field image and also with re-importing our synthetic image.\n", "- The `sigma_*` methods from `astropy.stats` work with image data that is clipped to within a certain number of deviations from the mean. `gaussian_fwhm_to_sigma` is a float for converting full width at half maximum values to standard deviations from the image mean.\n", "- The objects from `astropy.table` help with reading an modifiying tabular data.\n", + "- We download a copy of the Artifactory spectra with `astropy.utils.data.download_file`.\n", "- `astropy.wcs.WCS` creates a World Coordinate System object that is useful for transforming on-sky data from one patch to another.\n", - "- `glob.glob` lists local files that match a given pattern.\n", + "- `pathlib.Path` allows for the creation of file paths that work across operating systems.\n", "- The objects from `photutils.segmentation` do the work of analytically finding bright sources, separating those that overlap, and creating a catalog of the resulting information.\n", "- We use `matplotlib.pyplot` to preview the field image, the cutouts, and various stages of our synthetic image.\n", "- We use `numpy` to facilitate several specialized mathematical and array-related operations.\n", - "- `os` helps us create a new directory for the final cutouts from the synthetic image.\n", - "- `%matplotlib inline` is notebook \"magic\" that helps display in-notebook plots consistently for different users." + "- `zipfile` assists with unzipping the downloaded Artifactory files.\n", + "- Finally, `%matplotlib inline` is notebook \"magic\" that helps display in-notebook plots consistently for different users." ] }, { @@ -53,7 +56,9 @@ "outputs": [], "source": [ "import os\n", + "import zipfile\n", "from glob import glob\n", + "from pathlib import Path\n", "\n", "from astropy import units as u\n", "from astropy.coordinates import SkyCoord\n", @@ -63,6 +68,7 @@ "from astropy.stats import (gaussian_fwhm_to_sigma,\n", " sigma_clipped_stats, sigma_clip)\n", "from astropy.table import Table, join\n", + "from astropy.utils.data import download_file\n", "from astropy.wcs import WCS\n", "from photutils.segmentation import (detect_sources, deblend_sources,\n", " SourceCatalog)\n", @@ -417,9 +423,39 @@ "source": [ "### (Try to) Extract destination RA/Dec from spectra files\n", "\n", - "Note that this section's cells only run on a connection with access to the STScI VPN. They use copies of JWST pipeline files from May 19, 2021.\n", + "We download copies of Level 3 data products from the JWST pipeline dated May 19, 2021 and hosted in a STScI Box folder. (For more current files, visit the [Artifactory](https://bytesalad.stsci.edu/ui/repos/tree/General/jwst-pipeline%2Fdev%2Ftruth%2Ftest_nirspec_mos_spec3.).) The files are saved in this notebook's current location. If you prefer to save them elsewhere, change `filepath`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73c7cd0a-1eed-4c1e-a7af-16247d6991b6", + "metadata": {}, + "outputs": [], + "source": [ + "filepath = Path('./')\n", + "\n", + "# If necessary, download and extract spectra files\n", + "spec_link = 'https://stsci.box.com/shared/static/3rz8g1fizu6dh7zdymxouvdd8usnm3jc.zip'\n", + "spec_zip = filepath / 'artifactory_spectra-2021-05-19.zip'\n", + "spec_path = filepath / spec_zip.stem\n", "\n", - "To run them elsewhere and/or use more current files, visit the [Artifactory](https://bytesalad.stsci.edu/ui/repos/tree/General/jwst-pipeline%2Fdev%2Ftruth%2Ftest_nirspec_mos_spec3), ensure the `jwst-pipeline/dev/truth/test_nirspec_mos_spec3/` folder is the one selected in the directory tree, and download all files whose names begin with `jw00626-o030` and end with `nirspec_f170lp-g235m_x1d.fits` or `nirspec_f170lp-g235m_s2d.fits`. (The original version of this notebook uses six of these Level 3 data products.) Then, change `filepath` in the next cell to the location where you saved the downloaded files, remembering the trailing slash." + "if spec_path.exists():\n", + " print('Spectra already on disk.')\n", + "else:\n", + " if not (filepath / spec_zip).exists():\n", + " print(f\"Downloading '{spec_zip.name}'.\")\n", + " box_file = download_file(spec_link, cache=True)\n", + " \n", + " # place link to downloaded file in current directory\n", + " os.symlink(box_file, filepath / spec_zip)\n", + " \n", + " print('Extracting spectra.')\n", + " \n", + " # create target directory and extract spectra files \n", + " (filepath / spec_path).mkdir()\n", + " with zipfile.ZipFile(filepath / spec_zip, 'r') as zf:\n", + " zf.extractall(spec_path)" ] }, { @@ -430,9 +466,8 @@ "outputs": [], "source": [ "# view level 3 spectra FITS header information\n", - "filepath = '/user/jotor/jwst-pipeline-lvl3-copy/'\n", - "x1d_header = fits.getheader(filepath + 'jw00626-o030_s00000_nirspec_f170lp-g235m_x1d.fits', ext=1)\n", - "s2d_header = fits.getheader(filepath + 'jw00626-o030_s00000_nirspec_f170lp-g235m_s2d.fits', ext=1)" + "x1d_header = fits.getheader(spec_path / 'jw00626-o030_s00000_nirspec_f170lp-g235m_x1d.fits', ext=1)\n", + "s2d_header = fits.getheader(spec_path / 'jw00626-o030_s00000_nirspec_f170lp-g235m_s2d.fits', ext=1)" ] }, { @@ -472,7 +507,7 @@ "source": [ "# search for RA/Dec information from Artifactory observation files\n", "x1d_header_list = [fits.getheader(file, ext=1)\n", - " for file in glob(filepath + 'jw00626*x1d.fits')]\n", + " for file in spec_path.glob('jw00626*x1d.fits')]\n", "\n", "_ras, _decs = np.array([[h['SRCRA'], h['SRCDEC']] for h in x1d_header_list]).T\n", "_ras, _decs" @@ -712,7 +747,7 @@ "id": "8b518b39-3d22-42c4-a632-4c17801900a5", "metadata": {}, "source": [ - "We save the image to a local location. The default is this notebook's current directory; you can change that by adjusting `savepath` to your preferred path and remembering the trailing slash.\n", + "We save the image to a local location. The default is this notebook's current directory; you can change that by adjusting `savepath` to your preferred path.\n", "\n", "This cell will overwrite a same-named file if it already exists in that location." ] @@ -724,10 +759,10 @@ "metadata": {}, "outputs": [], "source": [ - "savepath = './'\n", + "savepath = Path('./')\n", "synth_file = 'synthetic_mosviz_image.fits'\n", "\n", - "fits.writeto(savepath + synth_file, synth_image,\n", + "fits.writeto(savepath / synth_file, synth_image,\n", " header=synth_wcs.to_header(), overwrite=True)" ] }, @@ -750,7 +785,7 @@ "metadata": {}, "outputs": [], "source": [ - "ccd_synth_img = CCDData.read(savepath + synth_file, unit='electron/s')" + "ccd_synth_img = CCDData.read(savepath / synth_file, unit='electron/s')" ] }, { @@ -764,7 +799,7 @@ "synth_cutout_list = [Cutout2D(ccd_synth_img, SkyCoord(r, d), synth_cutout_size)\n", " for r, d in zip(ras * u.deg, decs * u.deg)]\n", "\n", - "plt.imshow(synth_cutout_list[0].data, **imshow_params,\n", + "plt.imshow(synth_cutout_list[2].data, **imshow_params,\n", " vmin=0, vmax=ccd_synth_img.data.std())" ] }, @@ -788,10 +823,9 @@ }, "outputs": [], "source": [ - "savepath2 = './mosviz-cutouts/'\n", - "\n", - "if not os.path.exists(savepath2):\n", - " os.makedirs(savepath2)\n", + "cutout_dir = savepath / 'mosviz-cutouts/'\n", + "if not (savepath / cutout_dir).exists():\n", + " cutout_dir.mkdir()\n", "\n", "for i, cut in enumerate(synth_cutout_list):\n", " sdt = cut.data\n", @@ -802,7 +836,7 @@ " shd['OBJ_DEC'] = (decs[i], 'Source declination')\n", " shd['OBJ_ROT'] = (0, '')\n", " \n", - " fits.writeto(savepath2 + f\"synth_cutout{i}.fits\",\n", + " fits.writeto(cutout_dir / f\"synth_cutout{i}.fits\",\n", " sdt, header=shd, overwrite=True)\n", " \n", " plt.imshow(sdt, **imshow_params, vmin=0, vmax=ccd_synth_img.data.std())\n",