Skip to content

Commit

Permalink
Merge pull request #43 from eunkyuh/pandeia
Browse files Browse the repository at this point in the history
Updating the Pandeia notebook based on the comments from the RSP inte…
  • Loading branch information
tddesjardins authored Sep 17, 2024
2 parents 0500007 + 2888c7c commit 7124a14
Showing 1 changed file with 104 additions and 56 deletions.
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

0 comments on commit 7124a14

Please sign in to comment.