Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating the Pandeia notebook based on the comments from the RSP inte… #43

Merged
merged 1 commit into from
Sep 17, 2024
Merged
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
160 changes: 104 additions & 56 deletions content/notebooks/pandeia/pandeia.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"\n",
"## Imports\n",
"\n",
"Besides the Pandeia-related imports, we will use `scipy.optimize.minimize_scalar` to help with optimizing signal-to-noise ratios (SNRs)."
"Besides the Pandeia-related imports, we will use `scipy.optimize.minimize_scalar` to help with optimizing signal-to-noise ratios (SNRs), `scipy.interpolate.interp1d` to calculate a desired target magnitude for a given observing setup and `numpy` to handle numerical computing."
]
},
{
Expand All @@ -59,15 +59,17 @@
"source": [
"from pandeia.engine.calc_utils import build_default_calc\n",
"from pandeia.engine.perform_calculation import perform_calculation\n",
"from scipy.optimize import minimize_scalar"
"from scipy.optimize import minimize_scalar\n",
"from scipy import interpolate\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"id": "b6865f31-258d-4cf6-a6a0-1dae41773b02",
"metadata": {},
"source": [
"We set `FILTER` as global variable before beginning since all examples make use of the same F129 imaging filter."
"We set `FILTER` as global variable before beginning since all examples make use of the same F129 imaging filter. Please note that Pandeia's filter definition is case-sensitive and will only take lower-case letters for filter names. "
]
},
{
Expand All @@ -77,7 +79,7 @@
"metadata": {},
"outputs": [],
"source": [
"FILTER = 'f129'"
"FILTER = 'f129' # Pandeia's filter definitaion is case-sensitive and will only take lower-case letters for filter names "
]
},
{
Expand Down Expand Up @@ -105,7 +107,7 @@
"\n",
"In this first example, we calculate the expected SNR for a point source with a flat spectral distribution (default target) normalized to 25 AB magnitudes. We take three exposures in band F129 with the multi-accumulation (MA) table \"High Latitude Wide Area Survey - Imaging\", truncated after 5 resultants (91.20 seconds of total exposure time). MA tables describe the sequence of individual reads that are combined into resultants and comprise the up-the-ramp sampling during a single exposure of the WFI detectors. For more information on the WFI MA tables, please refer to the [RDox documentation](https://roman-docs.stsci.edu/raug/astronomers-proposal-tool-apt/appendix/appendix-wfi-multiaccum-tables).\n",
"\n",
"We first define the observing setup:"
"We first create a default calculation using Pandeia's built-in function `build_default_calc(<telescope>, <instrument>, <mode>)`: "
]
},
{
Expand All @@ -115,10 +117,50 @@
"metadata": {},
"outputs": [],
"source": [
"calc = build_default_calc('roman', 'wfi', 'imaging')\n",
"\n",
"calc['configuration']['instrument']['filter'] = FILTER\n",
"calc['configuration']['detector']['nexp'] = 3"
"calc = build_default_calc('roman', 'wfi', 'imaging') # Creating a default calculation using Roman's WFI with an imaing mode"
]
},
{
"cell_type": "markdown",
"id": "d8036f34",
"metadata": {},
"source": [
"Let's take a look at how the default calculation is set up:"
]
},
{
"cell_type": "markdown",
"id": "db27d9f0",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "a48d0642",
"metadata": {},
"outputs": [],
"source": [
"print(calc) # Print the default calculation"
]
},
{
"cell_type": "markdown",
"id": "013b4561",
"metadata": {},
"source": [
"The `build_default_calc` created a scene with a single point source to observe with F087 filter, High Latitude Wide Area Survey - Imaging (hlwas_imaging) MA table, truncated after 5 resultants, and with a single exposure. With the WFI, an exposure refers to a single multi-accum sequence of the detector array at a single dither point in the dither pattern. Next, we define the observing setup and make some changes to the default setting:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d5cdd524",
"metadata": {},
"outputs": [],
"source": [
"calc['configuration']['instrument']['filter'] = FILTER # Setting the filter to F129\n",
"calc['configuration']['detector']['nexp'] = 3 # Taking three exposures of multi-accum sequence"
]
},
{
Expand Down Expand Up @@ -146,7 +188,7 @@
"id": "55f5d8ac-126c-4b94-acd6-c26d9bfd63ac",
"metadata": {},
"source": [
"Finally, we perform the signal to noise calculation and print the result:"
"Finally, we perform the signal to noise calculation using Pandeia's another built-in function `perform_calculation` and print the result:"
]
},
{
Expand Down Expand Up @@ -177,11 +219,11 @@
"id": "ca56cbc7-ade0-4cc3-8e21-81a2c1b4edf9",
"metadata": {},
"source": [
"### Estimate the Limiting Magnitude for a Given SNR\n",
"### Calculate Corresponding Magnitude for a Given Setup\n",
"\n",
"In this example, we are interested in understanding the limited magnitude corresponding to a given SNR and for a specific observing setup.\n",
"In this example, we are interested in understanding the corresponding magnitude for a given SNR and for a specific observing setup.\n",
"\n",
"The following helper functions use Pandeia to simulate a range of scenes at different magnitudes in order to estimate the limiting magnitude corresponding to a given SNR. As above, we assume a point source with a flat spectrum, and the MA table is set to the \"High Latitude Wide Area Survey - Imaging\" table with 5 resultants."
"The following helper functions use Pandeia to simulate a range of scenes at different magnitudes in order to estimate the corresponding magnitude for a given SNR and a number of exposures. As above, we assume a point source with a flat spectrum, and the MA table is set to the \"High Latitude Wide Area Survey - Imaging\" table with 5 resultants."
]
},
{
Expand All @@ -191,50 +233,26 @@
"metadata": {},
"outputs": [],
"source": [
"def _mag2sn_(mag, calc, sntarget):\n",
" \"\"\"\n",
" Optimize a S/N ratio given a magnitude. This is a helper function used as\n",
" an argument for scipy's minimize_scalar() as used in compute_mag().\n",
" \n",
" Parameters\n",
" ----------\n",
" mag: TYPE??\n",
" The magnitude used in an iteration of minimize_scalar()\n",
" calc: TYPE??\n",
" A Pandeia calculation object\n",
" sntarget: TYPE??\n",
" Required S/N from the matching argument of compute_mag()\n",
" \n",
" \"\"\"\n",
" calc['scene'][0]['spectrum']['normalization']['norm_flux'] = mag\n",
" etc = perform_calculation(calc)['scalar']\n",
" \n",
" return (sntarget - etc['sn'])**2\n",
"\n",
"\n",
"def compute_mag(filt, sn, nexp, bracket=(18., 30.), xtol=1e-4):\n",
"def compute_mag(filt, nexp, bracket=(18, 30)):\n",
" \"\"\"\n",
" Method to compute the magnitude from S/N and number of exposures\n",
" \n",
" Parameters\n",
" ----------\n",
" filt : str\n",
" Name of Roman WFI filter\n",
" sn : float\n",
" Required S/N\n",
" nexp : int\n",
" Number of exposures\n",
" bracket : tuple\n",
" Range of magnitudes to test. default: (18., 30.)\n",
" xtold: float, default 1e-4\n",
" Target tolerance for minimizer\n",
" Range of magnitudes to test. default: (18, 30)\n",
"\n",
" \n",
" Returns\n",
" -------\n",
" mag : float\n",
" Optimal magnitude for specified S/N and number of exposures\n",
" report: dict\n",
" Pandeia dictionary with optimal parameters\n",
" mag_range : float\n",
" An array of magnitudes used to compute the SNRs\n",
" computed_snrs: float\n",
" An array of computed SNRs from Pandeia calculations\n",
" \"\"\"\n",
" \n",
" # Set up default Roman observation\n",
Expand All @@ -247,14 +265,38 @@
" # Set number of exposures and filter\n",
" calc['configuration']['detector']['nexp'] = nexp\n",
" calc['configuration']['instrument']['filter'] = filt\n",
" \n",
" res = minimize_scalar(_mag2sn_, bracket=bracket, args=(calc, sn),\n",
" method='brent', options={'xtol': xtol})\n",
" mag = res['x']\n",
" calc['scene'][0]['spectrum']['normalization']['norm_flux'] = mag\n",
" report = perform_calculation(calc)\n",
"\n",
" # Create an array of magnitudes range of interest\n",
" mag_range = np.arange(bracket[0], bracket[1]+1, 1)\n",
" # Create empty lists to save the computations\n",
" computed_snrs = []\n",
" # Compute the SNRs for a given magnitude\n",
" for m in range(len(mag_range)):\n",
" mag = mag_range[m]\n",
" calc['scene'][0]['spectrum']['normalization']['norm_flux'] = mag\n",
" report = perform_calculation(calc)\n",
" computed_snrs.append(report['scalar']['sn'])\n",
"\n",
" return mag_range, computed_snrs\n",
"\n",
"def _mag2sn_(mag_range, computed_snrs, sntarget):\n",
" \"\"\"\n",
" Calculate a magnitude given a desired SNR by interpolating (computed_snrs, mag_range) from compute_mag\n",
" \n",
" Parameters\n",
" ----------\n",
" mag_range: float\n",
" An array of magnitudes used in calculating a range of SNRs in compute_mag\n",
" computed_snrs: float\n",
" An array of computed SNR given the mag_range using Pandeia calculation object\n",
" sntarget: float\n",
" Required S/N\n",
" \n",
" return mag, report"
" \"\"\"\n",
" interpolator = interpolate.interp1d(computed_snrs, mag_range)\n",
" mag = interpolator(sntarget)\n",
"\n",
" return mag"
]
},
{
Expand All @@ -278,7 +320,9 @@
"sn = 5\n",
"nexp = 10\n",
"\n",
"mag, report = compute_mag(FILTER, sn, nexp)\n",
"# mag, report = compute_mag(FILTER, sn, nexp)\n",
"mag_range, computed_snrs = compute_mag(FILTER, nexp)\n",
"mag = _mag2sn_(mag_range, computed_snrs, sn)\n",
"print(f'Estimated magnitude: {mag:.2f}')"
]
},
Expand Down Expand Up @@ -370,7 +414,11 @@
" res = minimize_scalar(_nexp2sn_, bracket=bracket, bounds=bracket,\n",
" args=(calc, sn), method='bounded',\n",
" options={'xatol': xtol})\n",
" nexp = int(res['x'])\n",
" \n",
" # Take the optimization result and set it to nexp\n",
" # 'x' is the solution array in the optimization result object\n",
" # For more details on the minimize_scalar function, refer to https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize_scalar.html\n",
" nexp = int(res['x']) \n",
" calc['configuration']['detector']['nexp'] = nexp\n",
" report = perform_calculation(calc)\n",
" \n",
Expand Down Expand Up @@ -466,7 +514,7 @@
"id": "f3b4f34e-6dab-4d83-8f0e-0dc900c0e2b6",
"metadata": {},
"source": [
"## Aditional Resources\n",
"## Additional Resources\n",
"\n",
"- The Roman User Documentation's [\"Pandeia for Roman\"](https://roman-docs.stsci.edu/simulation-tools-handbook-home/pandeia-for-roman) page and associated overview.\n",
"- Full API references for [Pandeia Engine inputs](https://outerspace.stsci.edu/display/PEN/Pandeia+Engine+Input+API) and [Pandeia Engine outputs](https://outerspace.stsci.edu/display/PEN/Pandeia+Engine+Output+API).\n",
Expand All @@ -485,8 +533,8 @@
"source": [
"## About this notebook\n",
"\n",
"**Author:** Justin Otor \n",
"**Updated On:** 2024-05"
"**Author:** Justin Otor, Eunkyu Han \n",
"**Updated On:** 2024-09"
]
},
{
Expand Down
Loading