diff --git a/_config.yml b/_config.yml index 3cf6d03b8..894344bab 100644 --- a/_config.yml +++ b/_config.yml @@ -53,6 +53,7 @@ exclude_patterns: [notebooks/DrizzlePac/align_mosaics/align_mosaics.ipynb, notebooks/WFC3/dash/dash.ipynb, notebooks/WFC3/filter_transformations/filter_transformations.ipynb, notebooks/WFC3/flux_conversion_tool/flux_conversion_tool.ipynb, + notebooks/WFC3/image_displayer_analyzer/wfc3_image_displayer_analyzer.ipynb, notebooks/WFC3/ir_ima_visualization/IR_IMA_Visualization_with_an_Example_of_Time_Variable_Background.ipynb, notebooks/WFC3/ir_scattered_light_calwf3_corrections/Correcting_for_Scattered_Light_in_IR_Exposures_Using_calwf3_to_Mask_Bad_Reads.ipynb, notebooks/WFC3/ir_scattered_light_manual_corrections/Correcting_for_Scattered_Light_in_IR_Exposures_by_Manually_Subtracting_Bad_Reads.ipynb, diff --git a/_toc.yml b/_toc.yml index 89758b603..cec17e3ab 100644 --- a/_toc.yml +++ b/_toc.yml @@ -66,7 +66,7 @@ parts: # - file: notebooks/WFC3/filter_transformations/filter_transformations.ipynb # - file: notebooks/WFC3/flux_conversion_tool/flux_conversion_tool.ipynb - file: notebooks/WFC3/image_displayer_analyzer/wfc3_image_displayer_analyzer.ipynb -# - file: notebooks/WFC3/ir_ima_visualization/IR_IMA_Visualization_with_an_Example_of_Time_Variable_Background.ipynb + - file: notebooks/WFC3/ir_ima_visualization/IR_IMA_Visualization_with_an_Example_of_Time_Variable_Background.ipynb # - file: notebooks/WFC3/ir_scattered_light_calwf3_corrections/Correcting_for_Scattered_Light_in_IR_Exposures_Using_calwf3_to_Mask_Bad_Reads.ipynb # - file: notebooks/WFC3/ir_scattered_light_manual_corrections/Correcting_for_Scattered_Light_in_IR_Exposures_by_Manually_Subtracting_Bad_Reads.ipynb - file: notebooks/WFC3/persistence/wfc3_ir_persistence.ipynb diff --git a/notebooks/WFC3/ir_ima_visualization/IR_IMA_Visualization_with_an_Example_of_Time_Variable_Background.ipynb b/notebooks/WFC3/ir_ima_visualization/IR_IMA_Visualization_with_an_Example_of_Time_Variable_Background.ipynb index 98f7af2d1..7dc2f10eb 100644 --- a/notebooks/WFC3/ir_ima_visualization/IR_IMA_Visualization_with_an_Example_of_Time_Variable_Background.ipynb +++ b/notebooks/WFC3/ir_ima_visualization/IR_IMA_Visualization_with_an_Example_of_Time_Variable_Background.ipynb @@ -96,7 +96,6 @@ "- *matplotlib.pyplot* for plotting data\n", "- *astropy.io fits* for accessing FITS files\n", "- *astroquery* for downlaoding data from MAST\n", - "- *ginga* for scaling using zscale\n", "\n", "We import the following module:\n", "- *ima_visualization_and_differencing* to take the difference between reads, plot the ramp, and to visualize the difference in images\n" @@ -109,15 +108,10 @@ "outputs": [], "source": [ "import os\n", - "\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", - "import matplotlib.patheffects as path_effects\n", - "\n", "from astropy.io import fits\n", "from astroquery.mast import Observations\n", - "from ginga.util.zscale import zscale\n", - "\n", "import ima_visualization_and_differencing as diff\n", "\n", "%matplotlib inline" @@ -162,9 +156,9 @@ "metadata": {}, "outputs": [], "source": [ - "EX_OBS = Observations.query_criteria(obs_id = 'ICQTBB020')\n", + "EX_OBS = Observations.query_criteria(obs_id='ICQTBB020')\n", "EXOBS_Prods = Observations.get_product_list(EX_OBS)\n", - "yourProd = Observations.filter_products(EXOBS_Prods, obs_id = ['icqtbbbxq', 'icqtbbc0q'], extension = [\"_ima.fits\",\"_flt.fits\"])" + "yourProd = Observations.filter_products(EXOBS_Prods, obs_id=['icqtbbbxq', 'icqtbbc0q'], extension=[\"_ima.fits\", \"_flt.fits\"])" ] }, { @@ -182,7 +176,7 @@ "metadata": {}, "outputs": [], "source": [ - "Observations.download_products(yourProd, mrp_only = False, cache = False)" + "Observations.download_products(yourProd, mrp_only=False, cache=False)" ] }, { @@ -194,13 +188,13 @@ "\n", "The figure below shows the WFC3/IR file structure corresponding to [Figure 2.4 of the Data Handbook](https://hst-docs.stsci.edu/wfc3dhb/chapter-2-wfc3-data-structure/2-2-wfc3-file-structure). Note that for WFC3/IR data, each read or image set (IMSET) consists of five data arrays: SCI, ERR, DQ, SAMP, TIME. Consecutive MULTIACCUM readouts are stored in reverse chronological order, with [SCI,1] corresponding to the final, cumulative exposure. \n", "\n", - "\"Drawing\"\n", + "\"Diagram\n", "\n", "The table below lists the IMSET, SAMPNUM, and SAMPTIME for a WFC3/IR SPARS100 exposure, modified from [Section 7.7 of the Instrument Handbook](https://hst-docs.stsci.edu/wfc3ihb/chapter-7-ir-imaging-with-wfc3/7-7-ir-exposure-and-readout). Note that the image header keyword NSAMP reports a value of 16, but there are actually 15 science reads in the IMA file, following the 0th read (which has an exposure time of 0). While NSAMP keyword is reported in the primary header (extension 0), the SAMPNUM and SAMPTIME keywords may be found in the science header of each read, and these report the read (IMSET) number and the cumulative exposure time of each respective read. \n", "\n", "This table is similar to [Table 7.7](https://hst-docs.stsci.edu/wfc3ihb/chapter-7-ir-imaging-with-wfc3/7-7-ir-exposure-and-readout#id-7.7IRExposureandReadout-table7.8), except that the column labelled NSAMP in the handbook is really the SAMPNUM. Note that we have added a row at the top of the table to highlight that IMSET [SCI,16] corresponds to the 0th read.\n", "\n", - "\"Drawing\"" + "\"Table" ] }, { @@ -231,7 +225,7 @@ "flt_nominal = 'mastDownload/HST/icqtbbc0q/icqtbbc0q_flt.fits'\n", "\n", "image = fits.open(ima_scattered)\n", - "image.info()\n" + "image.info()" ] }, { @@ -258,10 +252,10 @@ "metadata": {}, "outputs": [], "source": [ - "sci16hdr = image['SCI',16].header\n", + "sci16hdr = image['SCI', 16].header\n", "SAMPNUM_sci16 = sci16hdr['SAMPNUM']\n", "SAMPTIME_sci16 = sci16hdr['SAMPTIME']\n", - "print(f'For sample number {SAMPNUM_sci16}, the exposure time is {SAMPTIME_sci16}s.')\n" + "print(f'For sample number {SAMPNUM_sci16}, the exposure time is {SAMPTIME_sci16}s.')" ] }, { @@ -270,7 +264,7 @@ "metadata": {}, "outputs": [], "source": [ - "sci1hdr = image['SCI',1].header\n", + "sci1hdr = image['SCI', 1].header\n", "SAMPNUM_sci1 = sci1hdr['SAMPNUM']\n", "SAMPTIME_sci1 = sci1hdr['SAMPTIME']\n", "print(f'For sample number {SAMPNUM_sci1}, the exposure time is {SAMPTIME_sci1:.3f}s.')\n", @@ -298,35 +292,32 @@ "metadata": {}, "outputs": [], "source": [ - "fig = plt.figure(figsize = (30, 30))\n", - "fig\n", + "fig = plt.figure(figsize=(30, 30))\n", "rows = 2\n", "columns = 2\n", + "files = [ima_scattered, flt_scattered, ima_nominal, flt_nominal]\n", "\n", - "files = [ima_scattered, flt_scattered, ima_nominal, flt_nominal] \n", - "# If only analyzing one image, please remove the second ima,flt pair from the list \n", + "# If only analyzing one image, please remove the second ima,flt pair from the list\n", + "subplot_titles = ['scattered', 'nominal']\n", "\n", - "for i,file in enumerate(files):\n", + "for i, file in enumerate(files):\n", " path, filename = os.path.split(file)\n", - " \n", - " image = fits.open(file)\n", "\n", - " ax = fig.add_subplot(rows, columns, i+1)\n", - " ax.set_title(filename, fontsize = 20)\n", - " \n", - " subplot_titles = ['scattered', 'nominal']\n", - " #Please change the vmin and vmax values to fit your own data\n", - " if i == 0 or i == 1:\n", - " ax.set_title(f'{filename}, {subplot_titles[i//2]}', fontsize = 20)\n", - " im = ax.imshow(image[\"SCI\", 1].data, origin = 'lower',cmap = 'Greys_r', vmin = 0.25, vmax = 1.7)\n", - " else:\n", - " ax.set_title(f'{filename}, {subplot_titles[i//2]}', fontsize = 20)\n", - " im = ax.imshow(image[\"SCI\", 1].data, origin = 'lower',cmap = 'Greys_r', vmin = 0.5, vmax = 1.2)\n", - " plt.colorbar(im, ax = ax)\n", + " with fits.open(file) as image:\n", + " ax = fig.add_subplot(rows, columns, i + 1)\n", + " title = f'{filename}, {subplot_titles[i//2]}'\n", + " ax.set_title(title, fontsize=20)\n", + "\n", + " # Please change the vmin and vmax values to fit your own data\n", + " vmin, vmax = (0.25, 1.7) if i < 2 else (0.5, 1.2)\n", + " im = ax.imshow(\n", + " image['SCI', 1].data, origin='lower', cmap='Greys_r', vmin=vmin, vmax=vmax\n", + " )\n", + " plt.colorbar(im, ax=ax)\n", "\n", - "plt.subplots_adjust(bottom = 0.2, right = 0.5, top = 0.5)\n", - "plt.rc('xtick', labelsize = 10) \n", - "plt.rc('ytick', labelsize = 10) " + "plt.subplots_adjust(bottom=0.2, right=0.5, top=0.5)\n", + "plt.rc('xtick', labelsize=10)\n", + "plt.rc('ytick', labelsize=10)" ] }, { @@ -354,10 +345,10 @@ "outputs": [], "source": [ "try:\n", - " diff.plot_ima_subplots(ima_filename = ima_scattered, vmin = 0, vmax = 2.2)\n", - " \n", + " diff.plot_ima_subplots(ima_filename=ima_scattered, vmin=0, vmax=2.2)\n", + "\n", "except FileNotFoundError:\n", - " print(\"No file by this name found\")\n" + " print(\"No file by this name found\")" ] }, { @@ -376,7 +367,7 @@ "outputs": [], "source": [ "try:\n", - " diff.plot_ima_subplots(ima_filename = ima_nominal, vmin = 0, vmax = 2)\n", + " diff.plot_ima_subplots(ima_filename=ima_nominal, vmin=0, vmax=2)\n", "\n", "except FileNotFoundError:\n", " print(\"No file by this name found\")" @@ -395,31 +386,31 @@ "metadata": {}, "outputs": [], "source": [ - "fig = plt.figure(figsize = (10, 8))\n", + "fig = plt.figure(figsize=(10, 8))\n", "\n", - "ima_files=[ima_scattered, ima_nominal] \n", - "#If only using one image, please remove the extraneous image from this list \n", + "ima_files = [ima_scattered, ima_nominal] \n", + "# If only using one image, please remove the extraneous image from this list \n", "\n", - "marker_select = ['o','s']\n", - "color_select = ['black','C0']\n", + "marker_select = ['o', 's']\n", + "color_select = ['black', 'C0']\n", + "plt.rcParams.update({'font.size': 15})\n", "for i, ima in enumerate(ima_files):\n", " path, filename = os.path.split(ima)\n", - " \n", + "\n", " cube, integ_time = diff.read_wfc3(ima)\n", - " median_fullframe = np.nanmedian(cube, axis = (0,1))\n", + " median_fullframe = np.nanmedian(cube, axis=(0, 1))\n", "\n", - " plt.rcParams.update({'font.size':15})\n", " plt.plot(integ_time[1:], median_fullframe[1:]*integ_time[1:],\n", - " marker = marker_select[i], markersize = 8, color = color_select[i], label = filename)\n", + " marker=marker_select[i], markersize=8, \n", + " color=color_select[i], label=filename)\n", " plt.legend()\n", "plt.grid()\n", - "plt.xlabel('Integ. Time (s)', fontsize = 15)\n", - "plt.ylabel('electrons', fontsize = 15)\n", - "plt.rc('xtick', labelsize = 15) \n", - "plt.rc('ytick', labelsize = 15) \n", - "plt.grid(visible = True)\n", - "_=plt.title(\"Comparison of Signal Accumulation Ramp in Nominal vs. Scattered Light Images\", fontsize=15)\n", - " " + "plt.xlabel('Integ. Time (s)', fontsize=15)\n", + "plt.ylabel('electrons', fontsize=15)\n", + "plt.rc('xtick', labelsize=15) \n", + "plt.rc('ytick', labelsize=15) \n", + "plt.grid(visible=True)\n", + "_ = plt.title(\"Comparison of Signal Accumulation Ramp in Nominal vs. Scattered Light Images\", fontsize=15)" ] }, { @@ -441,43 +432,51 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "scrolled": false - }, + "metadata": {}, "outputs": [], "source": [ - "fig = plt.figure(figsize = (50, 20))\n", + "fig = plt.figure(figsize=(50, 20))\n", "fig\n", "rows = 1\n", "columns = 2\n", "ima_files = [ima_scattered, ima_nominal] \n", - "#If only using one image, please remove the extraneous image from this list \n", + "# If only using one image, please remove the extraneous image from this list \n", "\n", "subplot_titles = ['scattered', 'nominal']\n", "\n", + "lhs_region = {\"x0\": 50, \"x1\": 250, \"y0\": 100, \"y1\": 900}\n", + "rhs_region = {\"x0\": 700, \"x1\": 900, \"y0\": 100, \"y1\": 900}\n", + "\n", + "plt.rcParams.update({'font.size': 40})\n", + "\n", + "for i, ima in enumerate(ima_files):\n", "\n", - "lhs_region={\"x0\":50,\"x1\":250,\"y0\":100,\"y1\":900}\n", - "rhs_region={\"x0\":700,\"x1\":900,\"y0\":100,\"y1\":900}\n", - "for i,ima in enumerate(ima_files):\n", - " \n", " path, filename = os.path.split(ima)\n", - " \n", + "\n", " cube, integ_time = diff.read_wfc3(ima)\n", + "\n", + " median_fullframe, median_lhs, median_rhs = diff.get_median_fullframe_lhs_rhs(cube, \n", + " lhs_region=lhs_region, \n", + " rhs_region=rhs_region)\n", " \n", - " median_fullframe, median_lhs, median_rhs = diff.get_median_fullframe_lhs_rhs(cube, lhs_region = lhs_region, rhs_region = rhs_region)\n", - " plt.rcParams.update({'font.size':40})\n", " ax = fig.add_subplot(rows, columns, i+1)\n", - " ax.plot(integ_time[1:], median_fullframe[1:]*integ_time[1:], 's', markersize = 25, label = 'Full Frame', color = 'black')\n", - " ax.plot(integ_time[1:], median_lhs[1:]*integ_time[1:], '<', markersize = 20, label = 'LHS', color = 'C1')\n", - " ax.plot(integ_time[1:], median_rhs[1:]*integ_time[1:], '>', markersize = 20, label = 'RHS', color= 'C2')\n", - " ax.set_ylim(0,1800)\n", + " ax.plot(integ_time[1:], median_fullframe[1:]*integ_time[1:], 's', \n", + " markersize=25, label='Full Frame', color='black')\n", + " \n", + " ax.plot(integ_time[1:], median_lhs[1:]*integ_time[1:], '<', \n", + " markersize=20, label='LHS', color='C1')\n", + " \n", + " ax.plot(integ_time[1:], median_rhs[1:]*integ_time[1:], '>', \n", + " markersize=20, label='RHS', color='C2')\n", + " \n", + " ax.set_ylim(0, 1800)\n", " ax.grid()\n", " ax.set_xlabel('Integ. Time (s)')\n", " ax.set_ylabel('electrons')\n", - " ax.legend(loc = 0)\n", - " _=ax.set_title(f'{filename}, {subplot_titles[i]}', fontsize = 40)\n", - " ax.tick_params(axis = \"x\", labelsize = 30) \n", - " ax.tick_params(axis = \"y\", labelsize = 30) " + " ax.legend(loc=0)\n", + " _ = ax.set_title(f'{filename}, {subplot_titles[i]}', fontsize=40)\n", + " ax.tick_params(axis=\"x\", labelsize=30) \n", + " ax.tick_params(axis=\"y\", labelsize=30) " ] }, { @@ -514,10 +513,15 @@ "metadata": {}, "outputs": [], "source": [ - "##If only using one image, please remove the extraneous image from this list \n", - "lhs_region = {\"x0\":50,\"x1\":250,\"y0\":100,\"y1\":900}\n", - "rhs_region = {\"x0\":700,\"x1\":900,\"y0\":100,\"y1\":900}\n", - "diff.plot_ramp_subplots(ima_files = [ima_scattered, ima_nominal], difference_method = 'cumulative', exclude_sources = False, ylims = [-0.3,0.3], lhs_region = lhs_region, rhs_region = rhs_region)" + "# If only using one image, please remove the extraneous image from this list \n", + "lhs_region = {\"x0\": 50, \"x1\": 250, \"y0\": 100, \"y1\": 900}\n", + "rhs_region = {\"x0\": 700, \"x1\": 900, \"y0\": 100, \"y1\": 900}\n", + "diff.plot_ramp_subplots(ima_files=[ima_scattered, ima_nominal], \n", + " difference_method='cumulative', \n", + " exclude_sources=False, \n", + " ylims=[-0.3, 0.3], \n", + " lhs_region=lhs_region, \n", + " rhs_region=rhs_region)" ] }, { @@ -540,9 +544,12 @@ "outputs": [], "source": [ "try:\n", - " lhs_region = {\"x0\":50,\"x1\":250,\"y0\":100,\"y1\":900}\n", - " rhs_region = {\"x0\":700,\"x1\":900,\"y0\":100,\"y1\":900}\n", - " diff.plot_ima_difference_subplots(ima_filename = ima_scattered, difference_method = 'cumulative', lhs_region = lhs_region, rhs_region = rhs_region)\n", + " lhs_region = {\"x0\": 50, \"x1\": 250, \"y0\": 100, \"y1\": 900}\n", + " rhs_region = {\"x0\": 700, \"x1\": 900, \"y0\": 100, \"y1\": 900}\n", + " diff.plot_ima_difference_subplots(ima_filename=ima_scattered, \n", + " difference_method='cumulative', \n", + " lhs_region=lhs_region, \n", + " rhs_region=rhs_region)\n", " \n", "except FileNotFoundError:\n", " print(\"No file by this name found\")" @@ -570,9 +577,12 @@ "outputs": [], "source": [ "try:\n", - " lhs_region = {\"x0\":50,\"x1\":250,\"y0\":100,\"y1\":900}\n", - " rhs_region = {\"x0\":700,\"x1\":900,\"y0\":100,\"y1\":900}\n", - " diff.plot_ima_difference_subplots(ima_filename = ima_nominal, difference_method = 'cumulative', lhs_region = lhs_region, rhs_region = rhs_region)\n", + " lhs_region = {\"x0\": 50, \"x1\": 250, \"y0\": 100, \"y1\": 900}\n", + " rhs_region = {\"x0\": 700, \"x1\": 900, \"y0\": 100, \"y1\": 900}\n", + " diff.plot_ima_difference_subplots(ima_filename=ima_nominal, \n", + " difference_method='cumulative', \n", + " lhs_region=lhs_region, \n", + " rhs_region=rhs_region)\n", "\n", "except FileNotFoundError:\n", " print(\"No file by this name found\")" @@ -609,10 +619,15 @@ "metadata": {}, "outputs": [], "source": [ - "#If only using one image, please remove the extraneous image from this list \n", - "lhs_region = {\"x0\":50,\"x1\":250,\"y0\":100,\"y1\":900}\n", - "rhs_region = {\"x0\":700,\"x1\":900,\"y0\":100,\"y1\":900}\n", - "diff.plot_ramp_subplots(ima_files = [ima_scattered, ima_nominal], difference_method = 'instantaneous', exclude_sources = True, ylims = [0.5,2.5], lhs_region = lhs_region, rhs_region = rhs_region)" + "# If only using one image, please remove the extraneous image from this list \n", + "lhs_region = {\"x0\": 50, \"x1\": 250, \"y0\": 100, \"y1\": 900}\n", + "rhs_region = {\"x0\": 700, \"x1\": 900, \"y0\": 100, \"y1\": 900}\n", + "diff.plot_ramp_subplots(ima_files=[ima_scattered, ima_nominal], \n", + " difference_method='instantaneous', \n", + " exclude_sources=True, \n", + " ylims=[0.5, 2.5], \n", + " lhs_region=lhs_region, \n", + " rhs_region=rhs_region)" ] }, { @@ -636,9 +651,12 @@ "outputs": [], "source": [ "try:\n", - " lhs_region = {\"x0\":50,\"x1\":250,\"y0\":100,\"y1\":900}\n", - " rhs_region = {\"x0\":700,\"x1\":900,\"y0\":100,\"y1\":900}\n", - " diff.plot_ima_difference_subplots(ima_filename = ima_scattered, difference_method = 'instantaneous', lhs_region = lhs_region, rhs_region = rhs_region)\n", + " lhs_region = {\"x0\": 50, \"x1\": 250, \"y0\": 100, \"y1\": 900}\n", + " rhs_region = {\"x0\": 700, \"x1\": 900, \"y0\": 100, \"y1\": 900}\n", + " diff.plot_ima_difference_subplots(ima_filename=ima_scattered, \n", + " difference_method='instantaneous', \n", + " lhs_region=lhs_region, \n", + " rhs_region=rhs_region)\n", "\n", "except FileNotFoundError:\n", " print(\"No file by this name found\")" @@ -664,7 +682,10 @@ "outputs": [], "source": [ "try:\n", - " diff.plot_ima_difference_subplots(ima_filename = ima_nominal, difference_method = 'instantaneous', lhs_region = lhs_region, rhs_region = rhs_region)\n", + " diff.plot_ima_difference_subplots(ima_filename=ima_nominal, \n", + " difference_method='instantaneous', \n", + " lhs_region=lhs_region, \n", + " rhs_region=rhs_region)\n", " \n", "except FileNotFoundError:\n", " print(\"No file by this name found\")" @@ -770,9 +791,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.0" + "version": "3.11.6" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/notebooks/WFC3/ir_ima_visualization/ima_visualization_and_differencing.py b/notebooks/WFC3/ir_ima_visualization/ima_visualization_and_differencing.py index d174df612..d43e744b7 100644 --- a/notebooks/WFC3/ir_ima_visualization/ima_visualization_and_differencing.py +++ b/notebooks/WFC3/ir_ima_visualization/ima_visualization_and_differencing.py @@ -5,6 +5,7 @@ from ginga.util.zscale import zscale import matplotlib.patheffects as path_effects + def read_wfc3(filename): ''' Read a full-frame IR image and return the datacube plus integration times for each read. @@ -24,26 +25,23 @@ def read_wfc3(filename): integ_time : array-like Integration times associated with the datacube in ascending order. ''' - with fits.open(filename) as f: hdr = f[0].header NSAMP = hdr['NSAMP'] hdr1 = f[1].header - cube = np.zeros((hdr1['NAXIS1'],hdr1['NAXIS2'],NSAMP), dtype = float) - integ_time = np.zeros(shape = (NSAMP)) + cube = np.zeros((hdr1['NAXIS1'], hdr1['NAXIS2'], NSAMP), dtype=float) + integ_time = np.zeros(shape=NSAMP) for i in range(1, NSAMP+1): - cube[:,:,i-1] = f[('SCI', i)].data + cube[:, :, i-1] = f[('SCI', i)].data integ_time[i-1] = f[('TIME', i)].header['PIXVALUE'] - cube = cube[:,:,::-1] + cube = cube[:, :, ::-1] integ_time = integ_time[::-1] return cube, integ_time - def compute_diff_imas(cube, integ_time, diff_method): - ''' Compute the difference in signal between reads of a WFC3 IR IMA file. @@ -66,10 +64,9 @@ def compute_diff_imas(cube, integ_time, diff_method): 1024x1024x(NSAMP-1) datacube of the differebce between IR IMA reads in ascending time order, where NSAMP is the number of samples taken. ''' - if diff_method == 'instantaneous': ima_j = cube[:, :, 1:] - ima_j_1 = cube[:,:,0:-1] + ima_j_1 = cube[:, :, 0:-1] t_0 = integ_time[0] t_j = integ_time[1:] t_j_1 = integ_time[0:-1] @@ -77,7 +74,7 @@ def compute_diff_imas(cube, integ_time, diff_method): diff = ((ima_j*(t_j-t_0))-(ima_j_1*(t_j_1-t_0)))/(t_j-t_j_1) elif diff_method == 'cumulative': - diff = cube[:,:,0:-1] - cube[:,:,1:] + diff = cube[:, :, 0:-1] - cube[:, :, 1:] else: # if an incorrect method is chosen raise an error raise ValueError(f"{diff_method} is an invalid method. The allowed methods are 'instantaneous' and 'cumulative'.") @@ -86,7 +83,6 @@ def compute_diff_imas(cube, integ_time, diff_method): def get_median_fullframe_lhs_rhs(cube, lhs_region, rhs_region): - ''' Compute the median in the full-frame image, the user-defined left side region, and the user-defined right side region. @@ -113,19 +109,19 @@ def get_median_fullframe_lhs_rhs(cube, lhs_region, rhs_region): median_rhs : array of floats The median signal of the right side of each read. ''' - - - median_full_frame = np.nanmedian(cube[5:-5,5:-5,:], axis = (0,1)) + median_full_frame = np.nanmedian(cube[5:-5, 5:-5, :], + axis=(0, 1)) median_lhs = np.nanmedian(cube[lhs_region['y0']:lhs_region['y1'], - lhs_region['x0']:lhs_region['x1'],:], axis = (0,1)) + lhs_region['x0']:lhs_region['x1'], :], + axis=(0, 1)) median_rhs = np.nanmedian(cube[rhs_region['y0']:rhs_region['y1'], - rhs_region['x0']:rhs_region['x1'],:], axis = (0,1)) - + rhs_region['x0']:rhs_region['x1'], :], + axis=(0, 1)) return median_full_frame, median_lhs, median_rhs + def get_std_fullframe_lhs_rhs(cube, lhs_region, rhs_region): - ''' Compute the standard deviation of the signal in the full-frame image, the user-defined left side region, and the user-defined right side region. @@ -154,20 +150,19 @@ def get_std_fullframe_lhs_rhs(cube, lhs_region, rhs_region): standard_dev_rhs : array of floats The standard deviation of the signal of the right side of each read. ''' - - - standard_dev_fullframe = np.nanstd(cube[5:-5,5:-5,:], axis = (0,1)) + standard_dev_fullframe = np.nanstd(cube[5:-5, 5:-5, :], + axis=(0, 1)) standard_dev_lhs = np.nanstd(cube[lhs_region['y0']:lhs_region['y1'], - lhs_region['x0']:lhs_region['x1'],:], axis = (0,1)) + lhs_region['x0']:lhs_region['x1'], :], + axis=(0, 1)) standard_dev_rhs = np.nanstd(cube[rhs_region['y0']:rhs_region['y1'], - rhs_region['x0']:rhs_region['x1'],:], axis = (0,1)) - - + rhs_region['x0']:rhs_region['x1'], :], + axis=(0, 1)) + return standard_dev_fullframe, standard_dev_lhs, standard_dev_rhs - + def plot_ramp(ima, integ_time, median_diff_fullframe, median_diff_lhs, median_diff_rhs): - ''' Plots the signal accumulation ramp of an IMA image. Each point is the median signal (in e-/s) of the difference between subsequent reads. The median signal difference is plotted for the full @@ -190,19 +185,22 @@ def plot_ramp(ima, integ_time, median_diff_fullframe, median_diff_lhs, median_di median_diff_rhs: array-like The median difference in signal between the right side of each read. ''' - - plt.plot(integ_time[2:], median_diff_fullframe[1:], 's', markersize = 25, label = 'Full Frame', color = 'black') - plt.plot(integ_time[2:], median_diff_lhs[1:], '<', markersize = 20, label = 'LHS', color = 'orange') - plt.plot(integ_time[2:], median_diff_rhs[1:], '>', markersize = 20, label = 'RHS', color = 'green') + plt.plot(integ_time[2:], median_diff_fullframe[1:], 's', markersize=25, + label='Full Frame', color='black') + plt.plot(integ_time[2:], median_diff_lhs[1:], '<', markersize=20, + label='LHS', color='orange') + plt.plot(integ_time[2:], median_diff_rhs[1:], '>', markersize=20, + label='RHS', color='green') ax = plt.gca() - for spine in ['top', 'bottom', 'left', 'right']: ax.spines[spine].set_visible(False) + for spine in ['top', 'bottom', 'left', 'right']: + ax.spines[spine].set_visible(False) plt.grid() plt.xlabel('SAMPTIME [s]') - plt.ylabel('$\mu$ [e-/s]') - plt.legend(loc = 0) + plt.ylabel(r'$\mu$ [e-/s]') + plt.legend(loc=0) plt.title(ima) - - + + def panel_plot(cube, integ_time, median_diff_full_frame, median_diff_lhs, median_diff_rhs, standard_dev_fullframe, standard_dev_lhs, standard_dev_rhs, diff_method): ''' @@ -245,7 +243,7 @@ def panel_plot(cube, integ_time, median_diff_full_frame, median_diff_lhs, median fig: figure object Panel plot with subplots showing the difference between subsequent IMA reads. - Above each panel, we print the median difference $\mu$ in the count rate over the entire image. + Above each panel, we print the median difference mu in the count rate over the entire image. Below each panel, we list the IMSET difference, along with the time interval between the two IMSETs. The statistics in orange (on the left and right side of each panel) give the median rate and standard deviation of each side of the image, respectively. The value in green 'delta' is the @@ -253,54 +251,52 @@ def panel_plot(cube, integ_time, median_diff_full_frame, median_diff_lhs, median The value in white "Ratio" gives the ratio of the median difference in orange for the left versus the right side. ''' - - - xlabel_list = ["SCI[16-15]","SCI[15-14]","SCI[14-13]","SCI[13-12]","SCI[12-11]", - "SCI[11-10]","SCI[10-9]","SCI[9-8]","SCI[8-7]","SCI[[7-6]]","SCI[6-5]", - "SCI[5-4]","SCI[4-3]","SCI[3-2]","SCI[2-1]"] + xlabel_list = ["SCI[16-15]", "SCI[15-14]", "SCI[14-13]", "SCI[13-12]", "SCI[12-11]", + "SCI[11-10]", "SCI[10-9]", "SCI[9-8]", "SCI[8-7]", "SCI[[7-6]]", "SCI[6-5]", + "SCI[5-4]", "SCI[4-3]", "SCI[3-2]", "SCI[2-1]"] fig, axarr = plt.subplots(4, 4) fig.set_size_inches(40, 40) fig.set_dpi(40) itime = integ_time[0:-1] - integ_time[1:] - diff = compute_diff_imas(cube, integ_time, diff_method = diff_method) - - + diff = compute_diff_imas(cube, integ_time, diff_method=diff_method) + for i, ax in enumerate(axarr.reshape(-1)): - if (i < cube.shape[-1]-2): - i=i+1 + if i < cube.shape[-1]-2: + i += 1 - diff_i = diff[:,:,i] - vmin,vmax = zscale(diff_i) + diff_i = diff[:, :, i] + vmin, vmax = zscale(diff_i) im = ax.imshow(np.abs(diff_i), cmap='Greys_r', origin='lower', - vmin = vmin, vmax = vmax) - ax.set_title(f'$\mu = ${median_diff_full_frame[i]:.2f}±{standard_dev_fullframe[i]:.2f} e-/s', fontsize = 30) - - text = ax.text(50, 500, f'{median_diff_lhs[i]:.3f}\n±\n{standard_dev_lhs[i]:.3f}', color='Orange', fontsize=30) + vmin=vmin, vmax=vmax) + title = fr'$\mu = ${median_diff_full_frame[i]:.2f}±{standard_dev_fullframe[i]:.2f} e-/s' + ax.set_title(title, fontsize=30) + text_lhs = f'{median_diff_lhs[i]:.3f}\n±\n{standard_dev_lhs[i]:.3f}' + text = ax.text(50, 500, text_lhs, color='Orange', fontsize=30) text.set_path_effects([path_effects.Stroke(linewidth=15, foreground='black'), - path_effects.Normal()]) - text = ax.text(700, 500, f'{median_diff_rhs[i]:.3f}\n±\n{standard_dev_rhs[i]:.3f}', color='Orange', fontsize=30) + path_effects.Normal()]) + text_rhs = f'{median_diff_rhs[i]:.3f}\n±\n{standard_dev_rhs[i]:.3f}' + text = ax.text(700, 500, text_rhs, color='Orange', fontsize=30) text.set_path_effects([path_effects.Stroke(linewidth=15, foreground='black'), - path_effects.Normal()]) - text = ax.text(200, 900, f'Ratio = {median_diff_lhs[i]/median_diff_rhs[i]:.2f}', color='White', fontsize=30) + path_effects.Normal()]) + text_ratio = f'Ratio = {median_diff_lhs[i]/median_diff_rhs[i]:.2f}' + text = ax.text(200, 900, text_ratio, color='White', fontsize=30) text.set_path_effects([path_effects.Stroke(linewidth=15, foreground='black'), - path_effects.Normal()]) - text = ax.text(300, 300, f'$\Delta = ${median_diff_lhs[i]-median_diff_rhs[i]:.2f}', color='#32CD32', fontsize=30) + path_effects.Normal()]) + text_delta = fr'$\Delta = ${median_diff_lhs[i]-median_diff_rhs[i]:.2f}' + text = ax.text(300, 300, text_delta, color='#32CD32', fontsize=30) text.set_path_effects([path_effects.Stroke(linewidth=15, foreground='black'), - path_effects.Normal()]) + path_effects.Normal()]) - cbar = plt.colorbar(im, ax = ax) - cbar.ax.tick_params(labelsize = 20) - + cbar = plt.colorbar(im, ax=ax) + cbar.ax.tick_params(labelsize=20) ax.set_yticklabels([]) ax.set_xticklabels([]) - ax.set_xlabel(f'{xlabel_list[i]}, $\Delta t = ${np.abs(itime[i]):.2f} sec', fontsize = 30) - + ax.set_xlabel(fr'{xlabel_list[i]}, $\Delta t = ${np.abs(itime[i]):.2f} sec', fontsize=30) else: - ax.set_axis_off() return fig @@ -321,7 +317,6 @@ def plot_ima_subplots(ima_filename, vmin, vmax): vmax: float Maximum magnitude for scaling the data range that the colormap covers. ''' - path, filename = os.path.split(ima_filename) cube, integ_time = read_wfc3(ima_filename) @@ -329,23 +324,22 @@ def plot_ima_subplots(ima_filename, vmin, vmax): fig_panel1, axarr = plt.subplots(4, 4) fig_panel1.set_size_inches(40, 40) fig_panel1.set_dpi(40) - plt.rcParams.update({'font.size':40}) - itime = integ_time[0:-1] - integ_time[1:] - read_title=np.arange(16,0,-1) + plt.rcParams.update({'font.size': 40}) + read_title = np.arange(16, 0, -1) for i, ax in enumerate(axarr.reshape(-1)): - im = ax.imshow(cube[:,:,i], cmap = 'Greys_r', origin = 'lower', vmin = vmin , vmax = vmax) + im = ax.imshow(cube[:, :, i], cmap='Greys_r', origin='lower', vmin=vmin, vmax=vmax) - cbar=plt.colorbar(im, ax = ax) - cbar.ax.tick_params(labelsize = 20) - ax.set_title(f'SCI, {read_title[i]}', fontsize = 40) + cbar = plt.colorbar(im, ax=ax) + cbar.ax.tick_params(labelsize=20) + ax.set_title(f'SCI, {read_title[i]}', fontsize=40) ax.set_yticklabels([]) ax.set_xticklabels([]) - _=fig_panel1.suptitle(filename, fontsize = 40) - plt.subplots_adjust(bottom = 0.3, right = 0.9, top = 0.95) - - + _ = fig_panel1.suptitle(filename, fontsize=40) + plt.subplots_adjust(bottom=0.3, right=0.9, top=0.95) + + def plot_ramp_subplots(ima_files, difference_method, ylims, exclude_sources, lhs_region, rhs_region): ''' Build a simple figure with subplots of IMA accumulation ramps. @@ -372,40 +366,42 @@ def plot_ramp_subplots(ima_files, difference_method, ylims, exclude_sources, lhs rhs_region : dict The four corners (x0, x1, y0, y1) of the right hand region. ''' - - fig = plt.figure(figsize = (50, 20)) + fig = plt.figure(figsize=(50, 20)) fig rows = 1 columns = 2 subplot_titles = ['scattered', 'nominal'] - for i,ima in enumerate(ima_files): - + for i, ima in enumerate(ima_files): path, filename = os.path.split(ima) cube, integ_time = read_wfc3(ima) - if exclude_sources == True: + if exclude_sources is True: cube[np.abs(cube) > 3] = np.nan - diff_cube = compute_diff_imas(cube, integ_time, diff_method = difference_method) - median_diff_fullframe, median_diff_lhs, median_diff_rhs = get_median_fullframe_lhs_rhs(diff_cube, lhs_region = lhs_region, rhs_region = rhs_region) + diff_cube = compute_diff_imas(cube, integ_time, diff_method=difference_method) + + median_diff_fullframe, median_diff_lhs, median_diff_rhs = ( + get_median_fullframe_lhs_rhs(diff_cube, + lhs_region=lhs_region, + rhs_region=rhs_region)) ax = fig.add_subplot(rows, columns, i+1) plot_ramp(ima, integ_time, median_diff_fullframe, median_diff_lhs, median_diff_rhs) - ax.set_ylim(ylims[0],ylims[1]) + ax.set_ylim(ylims[0], ylims[1]) - ax.tick_params(axis = "x", labelsize = 30) - ax.tick_params(axis = "y", labelsize = 30) + ax.tick_params(axis="x", labelsize=30) + ax.tick_params(axis="y", labelsize=30) - _=ax.set_title(f'{filename}, {subplot_titles[i]}', fontsize=50) + _ = ax.set_title(f'{filename}, {subplot_titles[i]}', fontsize=50) def plot_ima_difference_subplots(ima_filename, difference_method, lhs_region, rhs_region): ''' Build a complex panel plot of the difference between individual IMA reads. - The median difference $\mu$ in the count rate over the entire image is printed above each panel. Below each panel, + The median difference mu in the count rate over the entire image is printed above each panel. Below each panel, The IMSET difference, along with the time interval between the two IMSETs, is printed below. The statistics in orange (on the left and right side of each panel) give the median rate and standard deviation of each side of the image, respectively. The value in green 'delta' is the @@ -429,18 +425,30 @@ def plot_ima_difference_subplots(ima_filename, difference_method, lhs_region, rh ''' - path,filename = os.path.split(ima_filename) + path, filename = os.path.split(ima_filename) cube, integ_time = read_wfc3(ima_filename) - median_fullframe, median_lhs, median_rhs = get_median_fullframe_lhs_rhs(cube, lhs_region = lhs_region, rhs_region = rhs_region) - - diff_cube = compute_diff_imas(cube, integ_time, diff_method = difference_method) + median_fullframe, median_lhs, median_rhs = ( + get_median_fullframe_lhs_rhs(cube, + lhs_region=lhs_region, + rhs_region=rhs_region)) - median_diff_fullframe, median_diff_lhs, median_diff_rhs = get_median_fullframe_lhs_rhs(diff_cube, lhs_region = lhs_region, rhs_region = rhs_region) - standard_dev_fullframe, standard_dev_lhs, standard_dev_rhs = get_std_fullframe_lhs_rhs(diff_cube, lhs_region = lhs_region, rhs_region = rhs_region) + diff_cube = compute_diff_imas(cube, integ_time, diff_method=difference_method) - fig_0 = panel_plot(cube, integ_time, median_diff_fullframe, median_diff_lhs, median_diff_rhs, standard_dev_fullframe, standard_dev_lhs, standard_dev_rhs, diff_method = difference_method) - _=fig_0.suptitle(filename, fontsize = 40) - plt.subplots_adjust(bottom = 0.25, right = 0.9, top = 0.95) + median_diff_fullframe, median_diff_lhs, median_diff_rhs = ( + get_median_fullframe_lhs_rhs(diff_cube, + lhs_region=lhs_region, + rhs_region=rhs_region)) + + standard_dev_fullframe, standard_dev_lhs, standard_dev_rhs = ( + get_std_fullframe_lhs_rhs(diff_cube, + lhs_region=lhs_region, + rhs_region=rhs_region)) + fig_0 = panel_plot(cube, integ_time, median_diff_fullframe, median_diff_lhs, + median_diff_rhs, standard_dev_fullframe, standard_dev_lhs, + standard_dev_rhs, diff_method=difference_method) + + _ = fig_0.suptitle(filename, fontsize=40) + plt.subplots_adjust(bottom=0.25, right=0.9, top=0.95) diff --git a/notebooks/WFC3/ir_ima_visualization/requirements.txt b/notebooks/WFC3/ir_ima_visualization/requirements.txt index 6de0ed093..ee67db939 100644 --- a/notebooks/WFC3/ir_ima_visualization/requirements.txt +++ b/notebooks/WFC3/ir_ima_visualization/requirements.txt @@ -1,5 +1,5 @@ astropy==5.2.1 astroquery==0.4.6 -ginga==4.1.1 +ginga==4.0.1 matplotlib==3.7.0 numpy==1.23.4