diff --git a/_config.yml b/_config.yml index 32b353393..08636d5cc 100644 --- a/_config.yml +++ b/_config.yml @@ -50,5 +50,4 @@ html: # Exclude notebooks that have as-yet unresolved build failures (see tickets SPB-1153SPB-1160, SPB-1168) exclude_patterns: [notebooks/DrizzlePac/align_mosaics/align_mosaics.ipynb, notebooks/WFC3/dash/dash.ipynb, - notebooks/WFC3/flux_conversion_tool/flux_conversion_tool.ipynb, notebooks/WFC3/zeropoints/zeropoints.ipynb] diff --git a/notebooks/WFC3/flux_conversion_tool/flux_conversion_tool.ipynb b/notebooks/WFC3/flux_conversion_tool/flux_conversion_tool.ipynb index 02db84c58..5f256cfad 100644 --- a/notebooks/WFC3/flux_conversion_tool/flux_conversion_tool.ipynb +++ b/notebooks/WFC3/flux_conversion_tool/flux_conversion_tool.ipynb @@ -62,10 +62,11 @@ "\n", "## 1. Imports\n", "\n", - "This notebook assumes you have created the virtual environment in [WFC3 Library's](https://github.com/spacetelescope/WFC3Library) installation instructions.\n", + "This notebook assumes you have created the virtual environment in [WFC3 notebooks’](https://github.com/spacetelescope/hst_notebooks/blob/main/notebooks/WFC3/README.md) installation instructions.\n", "\n", "We import:\n", "- *os* for setting environment variables\n", + "- *tarfile* for extracting a .tar archive\n", "\n", "- *numpy* for handling array functions\n", "- *matplotlib.pyplot* for plotting data\n", @@ -83,21 +84,20 @@ "metadata": {}, "outputs": [], "source": [ - "%matplotlib notebook\n", - "\n", "import os\n", + "import tarfile\n", "\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", - "import synphot as syn\n", - "from synphot import SourceSpectrum, Observation\n", + "from synphot import SourceSpectrum\n", "from synphot.models import BlackBody1D, PowerLawFlux1D\n", "from synphot.units import convert_flux\n", "\n", "from astropy import units as u\n", "from synphot import units as su\n", "\n", + "%matplotlib inline\n", "vegaspec = SourceSpectrum.from_vega() " ] }, @@ -106,7 +106,7 @@ "id": "03e60162", "metadata": {}, "source": [ - "This section obtains the WFC3 throughput component tables for use with `synphot`. If reference files need to be downloaded, please uncomment and execute the code block below." + "This section obtains the WFC3 throughput component tables for use with `stsynphot`. This step only needs to be done once. If these reference files have already been downloaded, this section can be skipped." ] }, { @@ -116,8 +116,8 @@ "metadata": {}, "outputs": [], "source": [ - "# cmd_input = 'curl -O https://archive.stsci.edu/hlsps/reference-atlases/hlsp_reference-atlases_hst_multi_everything_multi_v11_sed.tar'\n", - "# os.system(cmd_input)" + "cmd_input = 'curl -O https://archive.stsci.edu/hlsps/reference-atlases/hlsp_reference-atlases_hst_multi_everything_multi_v11_sed.tar'\n", + "os.system(cmd_input)" ] }, { @@ -125,7 +125,7 @@ "id": "a60c88ec", "metadata": {}, "source": [ - "Once the downloaded is complete, unzip the file and set the environment variable `PYSYN_CDBS` to the path of the reference files. To do so, uncomment and execute the relevant line from the code block below. " + "Once the downloaded is complete, extract the file and set the environment variable `PYSYN_CDBS` to the path of the `trds` subdirectory. The next cell will do this for you, as long as the `.tar` file downloaded above has not been moved." ] }, { @@ -135,7 +135,12 @@ "metadata": {}, "outputs": [], "source": [ - "# os.environ['PYSYN_CDBS'] = '/path/to/my/reference/files/'" + "tar_archive = 'hlsp_reference-atlases_hst_multi_everything_multi_v11_sed.tar'\n", + "extract_to = 'hlsp_reference-atlases_hst_multi_everything_multi_v11_sed'\n", + "with tarfile.open(tar_archive, 'r') as tar:\n", + " tar.extractall(path=extract_to)\n", + "\n", + "os.environ['PYSYN_CDBS'] = 'hlsp_reference-atlases_hst_multi_everything_multi_v11_sed/grp/redcat/trds/'" ] }, { @@ -143,7 +148,7 @@ "id": "c4bbc869", "metadata": {}, "source": [ - "Now, after having set up `PYSYN_CDBS`, we import stsynphot." + "Now, after having set up `PYSYN_CDBS`, we import stsynphot. A warning regarding the Vega spectrum is expected here." ] }, { @@ -153,8 +158,7 @@ "metadata": {}, "outputs": [], "source": [ - "import stsynphot as stsyn\n", - "from stsynphot import band" + "import stsynphot as stsyn" ] }, { @@ -224,7 +228,7 @@ "\n", "- `synphot.models.BlackBody1D` outputs a function according to Planck's law, which means that the output unit carries an implicit \"per unit solid angle,\" in steradians. For a normalized blackbody, you can use `BlackBodyNorm1D`, whose output is normalized to a 1 solar radius star at a distance of 1 kpc, or multiply your source spectrum by some solid angle of your choosing.\n", "\n", - "- `synphot.models.PowerLawFlux1D` uses the definition $f(x) = A (\\frac{x}{x_0})^{-\\alpha}$, where $A$ is input flux (`flux_in`), and $x_0$ is the input wavelength (`wl_in`). Note the negative sign in front of the power law index $\\alpha$. The model can generate curves with $x$ as either frequency or wavelength, but the example here assumes that wavelength will be used. The y-axis unit will be taken from $A$. \n", + "- `synphot.models.PowerLawFlux1D` uses the definition $f(x) = A (\\frac{x}{x_0})^{-\\alpha}$, where $A$ is input flux (`flux_in`), and $x_0$ is the input wavelength (`wavelength_in`). Note the negative sign in front of the power law index $\\alpha$. The model can generate curves with $x$ as either frequency or wavelength, but the example here assumes that wavelength will be used. The y-axis unit will be taken from $A$. \n", "\n", "- A wide array of reference spectra are available for download from spectral atlases located [here](https://www.stsci.edu/hst/instrumentation/reference-data-for-calibration-and-tools/astronomical-catalogs).\n", "\n", @@ -237,16 +241,16 @@ "bb_temp = 5800 * u.K\n", "\n", "model = BlackBody1D(bb_temp)\n", - "spec = SourceSpectrum(model)\n", + "spectrum = SourceSpectrum(model)\n", "\n", "# Power law \n", "pl_index = 0\n", "\n", - "model = PowerLawFlux1D(amplitude=flux_in, x_0=wl_in, alpha=pl_index)\n", - "spec = SourceSpectrum(model)\n", + "model = PowerLawFlux1D(amplitude=flux_in, x_0=wavelength_in, alpha=pl_index)\n", + "spectrum = SourceSpectrum(model)\n", " \n", "# Load from a FITS table\n", - "spec = SourceSpectrum.from_file('/path/to/your/spectrum.fits')\n", + "spectrum = SourceSpectrum.from_file('/path/to/your/spectrum.fits')\n", "```\n", "\n", "The notebook has been set up to perform an extrapolation from $V = 0.0$ in the Vega system to the R-band in the same system, using the Vega spectrum defined in the imports cell. Further examples of input and output settings are available at the bottom of this notebook.\n", @@ -255,10 +259,10 @@ "### 2.4 User settings\n", "\n", "First, we define our conversion input settings:\n", - "- `val_in`: numerical value of input flux/mag (float)\n", + "- `value_in`: numerical value of input flux/mag (float)\n", "- `unit_in`: unit or mag system for input value\n", - "- `wl_bp_in`: input's wavelength (float) for flux, or bandpass obsmode (string) for magnitudes\n", - "- `wl_unit`: wavelength unit (used for plots, so needs to be specified even when using a bandpass)" + "- `waveband_in`: input's wavelength (float) for flux, or bandpass obsmode (string) for magnitudes. The use of \"waveband\" here is only for the purpose of variable naming, since this can be either a wavelength or a bandpass.\n", + "- `wavelength_unit`: wavelength unit (used for plots, so needs to be specified even when using a bandpass)" ] }, { @@ -268,11 +272,10 @@ "metadata": {}, "outputs": [], "source": [ - "val_in = 0.0\n", - "unit_in = su.VEGAMAG\n", - "wl_bp_in = 'johnson, v'\n", - "\n", - "wl_unit = u.nm " + "value_in = 0.0\n", + "unit_in = su.VEGAMAG\n", + "waveband_in = 'johnson, v'\n", + "wavelength_unit = u.nm " ] }, { @@ -282,7 +285,7 @@ "source": [ "Next, we define our conversion output settings:\n", "- `unit_out`: unit or mag system for the output\n", - "- `wl_bp_out`: wavelength (float) or bandpass obsmode (string) to find output for; if a wavelength, the unit specified in the cell above by `wl_unit` will be used." + "- `waveband_out`: wavelength (float) or bandpass obsmode (string) to find output for; if a wavelength, the unit specified in the cell above by `wavelength_unit` will be used." ] }, { @@ -292,8 +295,8 @@ "metadata": {}, "outputs": [], "source": [ - "unit_out = su.VEGAMAG\n", - "wl_bp_out = 'cousins, r'" + "unit_out = su.VEGAMAG\n", + "waveband_out = 'cousins, r'" ] }, { @@ -311,7 +314,7 @@ "metadata": {}, "outputs": [], "source": [ - "spec = vegaspec" + "spectrum = vegaspec" ] }, { @@ -344,9 +347,8 @@ "metadata": {}, "outputs": [], "source": [ - "quant_in = val_in * unit_in\n", - "\n", - "mag_systems = [u.STmag, u.ABmag, su.VEGAMAG]\n", + "quantity_in = value_in * unit_in\n", + "mag_systems = [u.STmag, u.ABmag, su.VEGAMAG]\n", "flux_systems = ['spectral flux density', 'spectral flux density wav', \n", " 'photon flux density', 'photon flux density wav']" ] @@ -381,27 +383,18 @@ "outputs": [], "source": [ "if unit_in in mag_systems:\n", - " \n", - " mag_in = quant_in\n", - " \n", - " band_in = band(wl_bp_in)\n", - " wl_in = band_in.pivot().to(wl_unit)\n", - " \n", - " flux_in = convert_flux(wl_in, quant_in, su.PHOTLAM,\n", + " mag_in = quantity_in\n", + " bandpass_in = stsyn.band(waveband_in)\n", + " wavelength_in = bandpass_in.pivot().to(wavelength_unit)\n", + " flux_in = convert_flux(wavelength_in, quantity_in, su.PHOTLAM,\n", " vegaspec=vegaspec)\n", - " \n", " plot_unit = su.PHOTLAM\n", - " \n", - " plot_flux_in = convert_flux(wl_in, flux_in, plot_unit)\n", - " \n", + " plot_flux_in = convert_flux(wavelength_in, flux_in, plot_unit)\n", "elif unit_in.physical_type in flux_systems:\n", - " \n", - " flux_in = quant_in\n", - " wl_in = wl_bp_in * wl_unit \n", - " \n", + " flux_in = quantity_in\n", + " wavelength_in = waveband_in * wavelength_unit \n", " plot_unit = unit_in\n", - " plot_flux_in = convert_flux(wl_in, flux_in, plot_unit)\n", - "\n", + " plot_flux_in = convert_flux(wavelength_in, flux_in, plot_unit)\n", "else:\n", " print('unit_in not a flux density unit or magnitude system')" ] @@ -429,20 +422,14 @@ "cell_type": "code", "execution_count": null, "id": "5928f11f", - "metadata": { - "scrolled": false - }, + "metadata": {}, "outputs": [], "source": [ "if unit_out in mag_systems:\n", - " \n", - " band_out = band(wl_bp_out)\n", - " wl_out = band_out.pivot().to(wl_unit)\n", - "\n", + " bandpass_out = stsyn.band(waveband_out)\n", + " wavelength_out = bandpass_out.pivot().to(wavelength_unit)\n", "elif unit_out.physical_type in flux_systems:\n", - " \n", - " wl_out = wl_bp_out * wl_unit\n", - "\n", + " wavelength_out = waveband_out * wavelength_unit\n", "else:\n", " print('unit_out not a flux density unit or magnitude system') " ] @@ -462,9 +449,8 @@ "metadata": {}, "outputs": [], "source": [ - "scale = convert_flux(wl_in, flux_in, su.PHOTLAM) / spec(wl_in)\n", - "\n", - "scale_spec = spec * scale" + "scale = convert_flux(wavelength_in, flux_in, su.PHOTLAM) / spectrum(wavelength_in)\n", + "scaled_spectrum = spectrum * scale" ] }, { @@ -486,18 +472,14 @@ "outputs": [], "source": [ "if unit_out in mag_systems:\n", - " \n", - " flux_out = convert_flux(wl_out, scale_spec(wl_out), unit_out,\n", + " flux_out = convert_flux(wavelength_out, scaled_spectrum(wavelength_out), unit_out,\n", " vegaspec=vegaspec)\n", - " \n", - " plot_flux_out = convert_flux(wl_out, scale_spec(wl_out), plot_unit)\n", - " \n", + " plot_flux_out = convert_flux(wavelength_out, scaled_spectrum(wavelength_out), plot_unit)\n", "else:\n", - " flux_out = convert_flux(wl_out, scale_spec(wl_out), unit_out)\n", + " flux_out = convert_flux(wavelength_out, scaled_spectrum(wavelength_out), unit_out)\n", + " plot_flux_out = convert_flux(wavelength_out, scaled_spectrum(wavelength_out), plot_unit)\n", " \n", - " plot_flux_out = convert_flux(wl_out, scale_spec(wl_out), plot_unit)\n", - " \n", - "val_out = flux_out.value" + "value_out = flux_out.value" ] }, { @@ -515,8 +497,9 @@ "metadata": {}, "outputs": [], "source": [ - "print('Input: {:.4} {} at {:.1f} {}\\n'.format(float(val_in), str(unit_in), wl_in.value, str(wl_in.unit)))\n", - "print('Output: {:.4} {} at {:.1f} {}'.format(float(val_out), str(unit_out), wl_out.value, str(wl_out.unit)))" + "print(f'Input: {value_in:.4f} {unit_in:s} at {wavelength_in.value:.1f} {wavelength_in.unit:s}\\n')\n", + "print(f'Input: {value_out:.4f} {unit_out:s} at {wavelength_out.value:.1f} {wavelength_out.unit:s}\\n')\n", + "# print(f'Output: {float(value_out):.4} {} at {:.1f} {}'.format(, str(unit_out), wavelength_out.value, str(wavelength_out.unit)))" ] }, { @@ -536,22 +519,17 @@ "metadata": {}, "outputs": [], "source": [ - "wl_settings = [wl.value for wl in [wl_in, wl_out]]\n", - "\n", - "short = min(wl_settings)\n", - "long = max(wl_settings)\n", + "wavelength_settings = [wl.value for wl in [wavelength_in, wavelength_out]]\n", + "short = min(wavelength_settings)\n", + "long = max(wavelength_settings)\n", "\n", - "if short == long: # In case wl_in == wl_out\n", + "if short == long: # In case wavelength_in == wavelength_out\n", " diff = 10.\n", - " \n", "else:\n", " diff = long - short\n", - "\n", "right = long + diff\n", - "\n", "left = max([short - diff, 0.1])\n", - "\n", - "waves = np.linspace(left, right, 10000) * wl_unit" + "wavelength_space = np.linspace(left, right, 10000) * wavelength_unit" ] }, { @@ -569,11 +547,9 @@ "metadata": {}, "outputs": [], "source": [ - "if wl_in.value > wl_out.value:\n", - " \n", + "if wavelength_in.value > wavelength_out.value:\n", " c_in = 'r'\n", " c_out = 'b'\n", - " \n", "else: \n", " c_in = 'b'\n", " c_out = 'r'" @@ -591,47 +567,39 @@ "cell_type": "code", "execution_count": null, "id": "8bea8f73", - "metadata": { - "scrolled": false - }, + "metadata": {}, "outputs": [], "source": [ "plt.figure()\n", "\n", "# Plot spectrum\n", - "\n", - "plt.plot(waves, scale_spec(waves, flux_unit=plot_unit), c='k')\n", + "plt.plot(wavelength_space, scaled_spectrum(wavelength_space, flux_unit=plot_unit), c='k', label='Source Spectrum')\n", "\n", "# Plot input\n", - "\n", - "plt.plot(wl_in.value, plot_flux_in.value,\n", + "plt.plot(wavelength_in.value, plot_flux_in.value,\n", " marker='o', color=c_in, ls='none', \n", " label='Input: {:.4} {} at {:.1f} {}'.format(\n", - " float(val_in), str(unit_in), wl_in.value, str(wl_in.unit)))\n", + " float(value_in), str(unit_in), wavelength_in.value, str(wavelength_in.unit)))\n", "\n", "# Plot output\n", - "\n", - "plt.plot(wl_out.value, plot_flux_out.value,\n", + "plt.plot(wavelength_out.value, plot_flux_out.value,\n", " marker='s', color=c_out, ls='none', \n", " label='Output: {:.4} {} at {:.1f} {}'.format(\n", - " float(val_out), str(unit_out), wl_out.value, str(wl_out.unit)))\n", + " float(value_out), str(unit_out), wavelength_out.value, str(wavelength_out.unit)))\n", "\n", "# Set heights for dotted lines to markers as % of plot range\n", - "\n", "bottom, top = plt.ylim()\n", "yrange = top - bottom\n", "inheight = (plot_flux_in.value - bottom) / yrange\n", "outheight = (plot_flux_out.value - bottom) / yrange\n", "\n", "# Plot dotted lines to markers\n", - "\n", - "plt.axvline(wl_in.to(wl_unit).value, ymax=inheight, ls=':', c=c_in)\n", - "plt.axvline(wl_out.to(wl_unit).value, ymax=outheight, ls=':', c=c_out)\n", + "plt.axvline(wavelength_in.to(wavelength_unit).value, ymax=inheight, ls=':', c=c_in)\n", + "plt.axvline(wavelength_out.to(wavelength_unit).value, ymax=outheight, ls=':', c=c_out)\n", "\n", "# Miscellaneous\n", - "\n", "plt.ylabel('Flux ({})'.format(str(plot_unit)))\n", - "plt.xlabel('Wavelength ({})'.format(str(wl_unit)))\n", + "plt.xlabel('Wavelength ({})'.format(str(wavelength_unit)))\n", "plt.legend(fontsize='small') \n", "plt.tight_layout()" ] @@ -659,23 +627,19 @@ "outputs": [], "source": [ "# Input: 3631 Jy at 550. nm\n", - "\n", - "val_in = 3631. \n", - "unit_in = u.Jy\n", - "wl_bp_in = 550.\n", - "\n", - "wl_unit = u.nm\n", + "value_in = 3631. \n", + "unit_in = u.Jy\n", + "waveband_in = 550.\n", + "wavelength_unit = u.nm\n", "\n", "# Output: Johnson V mag (AB)\n", - "\n", - "unit_out = u.ABmag\n", - "wl_bp_out = 'Johnson, V'\n", + "unit_out = u.ABmag\n", + "waveband_out = 'Johnson, V'\n", " \n", "# Spectrum: Flat power law in F_nu\n", - "\n", "pl_index = 0\n", - "model = PowerLawFlux1D(amplitude=flux_in, x_0=wl_in, alpha=pl_index)\n", - "spec = SourceSpectrum(model)" + "model = PowerLawFlux1D(amplitude=flux_in, x_0=wavelength_in, alpha=pl_index)\n", + "spectrum = SourceSpectrum(model)" ] }, { @@ -696,20 +660,16 @@ "outputs": [], "source": [ "# Input: 1.234e-8 flam at 500. nm\n", - "\n", - "val_in = 1.234e-8 \n", - "unit_in = su.FLAM\n", - "wl_bp_in = 500.\n", - "\n", - "wl_unit = u.nm\n", + "value_in = 1.234e-8 \n", + "unit_in = su.FLAM\n", + "waveband_in = 500.\n", + "wavelength_unit = u.nm\n", "\n", "# Output: flam at 800. nm\n", - "\n", - "unit_out = su.FLAM\n", - "wl_bp_out = 800.\n", + "unit_out = su.FLAM\n", + "waveband_out = 800.\n", " \n", "# Spectrum: 5800 K blackbody\n", - "\n", "bb_temp = 5800 * u.K\n", "model = BlackBody1D(bb_temp)\n", "spec = SourceSpectrum(model)" @@ -733,22 +693,19 @@ "outputs": [], "source": [ "# Input: 1.234e-21 fnu at 686. nm\n", - "\n", - "val_in = 1.234e-21 \n", - "unit_in = su.FNU\n", - "wl_bp_in = 686.\n", - "\n", - "wl_unit = u.nm\n", + "value_in = 1.234e-21 \n", + "unit_in = su.FNU\n", + "waveband_in = 686.\n", + "wavelength_unit = u.nm\n", "\n", "# Output: photnu at 686. nm\n", - "\n", - "unit_out = su.PHOTNU\n", - "wl_bp_out = 686.\n", + "unit_out = su.PHOTNU\n", + "waveband_out = 686.\n", " \n", "# Spectrum: 5800 K blackbody\n", "bb_temp = 5800 * u.K\n", "model = BlackBody1D(bb_temp)\n", - "spec = SourceSpectrum(model)" + "spectrum = SourceSpectrum(model)" ] }, { @@ -769,25 +726,20 @@ "outputs": [], "source": [ "# Input: STmag = 12.240, F606W filter on WFC3 UVIS 2\n", - "\n", - "val_in = 12.240 \n", - "unit_in = u.STmag\n", - "wl_bp_in = 'wfc3, uvis2, f606w, mjd#59367'\n", - "\n", - "wl_unit = u.nm\n", + "value_in = 12.240 \n", + "unit_in = u.STmag\n", + "waveband_in = 'wfc3, uvis2, f606w, mjd#59367'\n", + "wavelength_unit = u.nm\n", "\n", "# Output: Johnson V mag (AB)\n", - "\n", - "unit_out = u.STmag\n", - "wl_bp_out = 'Johnson, V'\n", + "unit_out = u.STmag\n", + "waveband_out = 'Johnson, V'\n", " \n", "# Spectrum: Flat power law in F_lambda\n", - "\n", "pl_index = 0\n", - "\n", "model = PowerLawFlux1D(amplitude=convert_flux(606 * u.nm, 1., su.FLAM), x_0=606 * u.nm, alpha=pl_index)\n", "spec = SourceSpectrum(model)\n", - "model = PowerLawFlux1D(amplitude=flux_in, x_0=wl_in, alpha=pl_index)" + "model = PowerLawFlux1D(amplitude=flux_in, x_0=wavelength_in, alpha=pl_index)" ] }, { @@ -869,7 +821,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.6" + "version": "3.11.6" } }, "nbformat": 4, diff --git a/notebooks/WFC3/flux_conversion_tool/requirements.txt b/notebooks/WFC3/flux_conversion_tool/requirements.txt index 2a8a2f707..74ad5e613 100644 --- a/notebooks/WFC3/flux_conversion_tool/requirements.txt +++ b/notebooks/WFC3/flux_conversion_tool/requirements.txt @@ -1,5 +1,5 @@ -astropy==5.2.1 -matplotlib==3.7.0 -numpy==1.23.4 +astropy +matplotlib==3.8.3 +numpy==1.26.4 stsynphot==1.2.0 synphot==1.1.1