diff --git a/_config.yml b/_config.yml index c2ba711e2..17952b3e2 100644 --- a/_config.yml +++ b/_config.yml @@ -50,7 +50,6 @@ exclude_patterns: [notebooks/DrizzlePac/align_mosaics/align_mosaics.ipynb, notebooks/WFC3/exception_report/wfc3_exception_report.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 b381f5262..9a55f87e7 100644 --- a/_toc.yml +++ b/_toc.yml @@ -65,7 +65,7 @@ parts: # - file: notebooks/WFC3/exception_report/wfc3_exception_report.ipynb # - 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/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_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 diff --git a/notebooks/WFC3/image_displayer_analyzer/README.md b/notebooks/WFC3/image_displayer_analyzer/README.md index 4525ced2c..a7540300f 100755 --- a/notebooks/WFC3/image_displayer_analyzer/README.md +++ b/notebooks/WFC3/image_displayer_analyzer/README.md @@ -1,21 +1,26 @@ -In this tutorial, we present `display_image`, a tool for displaying full images with metadata, individual WFC3/UVIS chip images, a section of an image with various colormaps/scaling, and individual WFC3/IR `ima` reads. In addition, we present `row_column_stats`, a tool for computing row and column statistics for the types of WFC3 images previously mentioned. +In this tutorial, we present `display_image`, a tool for displaying full images with metadata, individual WFC3/UVIS chip images, +a section of an image with various colormaps/scaling, and individual WFC3/IR `ima` reads. In addition, we present +`row_column_stats`, a tool for computing row and column statistics for the types of WFC3 images previously mentioned. This directory, once unzipped, should contain this `README.md`, the image displayer tool `display_image.py`, the row and column statistic -tool `row_column_stats.py`, and the Jupyter Notebook tutorial -`wfc3_imageanalysis.ipynb`. Both of these tools are meant to be used inside of -a Jupyter Notebook. +tool `row_column_stats.py`, a `requirements.txt` file for creating a virtual +environment, and the Jupyter Notebook tutorial `wfc3_imageanalysis.ipynb`. +These tools are meant to be used inside a Jupyter Notebook. -In order to run the Jupyter Notebook you must create the virtual -environment in [WFC3 Library's](https://github.com/spacetelescope/WFC3Library) -installation instructions. No additional packages are required to run this -Jupyter Notebook. +To run this Jupyter Notebook, you must have created a virtual environment that contains (at minimum) the packages listed in the +requirements.txt file that is included within the repository. We recommend creating a new conda environment using the requirements file: -These tools (specifically `display_image`) look much better in Jupyter Lab -rather than the classic Jupyter Notebook. If your environment has Jupyter Lab -installed it's recommended you use that to run the `.ipynb` file. If you're -interested in adding Jupyter Lab to your environment see the install -instructions on the [Jupyter website](https://jupyter.org/install). +``` +$ conda create -n img_disp python=3.11 +$ conda activate img_disp +$ pip install -r requirements.txt +``` -Questions or concerns should be sent to the [HST Help Desk](https://stsci.service-now.com/hst). +The tools in this notebook (specifically `display_image`) look much +better in Jupyter Lab rather than in the classic Jupyter Notebook. If your +environment has Jupyter Lab installed it's recommended you use that to run the +.ipynb file. See the [Jupyter website](https://jupyter.org/install) for more info. + +Please submit any questions or comments to the [WFC3 Help Desk](https://stsci.service-now.com/hst). --------------------------------------------------------------------- diff --git a/notebooks/WFC3/image_displayer_analyzer/display_image.py b/notebooks/WFC3/image_displayer_analyzer/display_image.py index 922479239..b9f046808 100755 --- a/notebooks/WFC3/image_displayer_analyzer/display_image.py +++ b/notebooks/WFC3/image_displayer_analyzer/display_image.py @@ -1,23 +1,23 @@ #! /usr/bin/env python - -import numpy as np import sys from astropy.io import fits -from ginga.util import zscale +from astropy.visualization import ZScaleInterval import matplotlib.pyplot as plt +import numpy as np + def display_image(filename, - colormaps=['Greys_r','Greys_r','inferno_r'], - scaling=[(None,None),(None,None),(None,None)], + colormaps=['Greys_r', 'Greys_r', 'inferno_r'], + scaling=[(None, None), (None, None), (None, None)], printmeta=False, ima_multiread=False, - figsize=(18,18), + figsize=(18, 18), dpi=200): - - """ A function to display the 'SCI', 'ERR/WHT', and 'DQ/CTX' arrays - of any WFC3 fits image. This function returns nothing, but will display - the requested image on the screen when called. + """ + A function to display the 'SCI', 'ERR/WHT', and 'DQ/CTX' arrays + of any WFC3 fits image. This function returns nothing, but will display + the requested image on the screen when called. Authors ------- @@ -51,8 +51,8 @@ def display_image(filename, List of real numbers to act as scalings for the SCI, ERR, and DQ arrays. The first element in the list is for the SCI array the second is for the ERR array and the third element in the list is for the DQ extension. If - no scalings are given the default scaling will use - ginga.util.zscale.zscale(). All three scalings must be provided even if + no scalings are given the default scaling will use astropy.visualization + ZScaleInterval.get_limits(). All three scalings must be provided even if only changing 1-2 scalings. E.g. to change SCI array scaling: scaling = [(5E4,8E4),(None,None),(None,None)] @@ -66,11 +66,11 @@ def display_image(filename, plotted. If ima_multiread is set to False only the final read of the ima (ext 1) will be plotted. - figsize: (float,float) - The width, height of the figure. Default is (18,18) + figsize: (Float,Float) + The width, height of the figure. Default is (18,18). - dpi: float - The resolution of the figure in dots-per-inch. Default is 200 + dpi: Float + The resolution of the figure in dots-per-inch. Default is 200. Returns ------- @@ -108,7 +108,7 @@ def display_image(filename, print("Invalid image section specified") return 0, 0 try: - xstart = int(xsec[: xs]) + xstart = int(xsec[:xs]) except ValueError: print("Problem getting xstart") return @@ -132,7 +132,6 @@ def display_image(filename, print("Problem getting yend") return - bunit = get_bunit(h1) detector = h['detector'] issubarray = h['subarray'] si = h['primesi'] @@ -151,33 +150,32 @@ def display_image(filename, print('-'*44) print(f"Filter = {h['filter']}, Date-Obs = {h['date-obs']} T{h['time-obs']},\nTarget = {h['targname']}, Exptime = {h['exptime']}, Subarray = {issubarray}, Units = {h1['bunit']}\n") - if detector == 'UVIS': - if ima_multiread == True: + if ima_multiread is True: sys.exit("keyword argument 'ima_multiread' can only be set to True for 'ima.fits' files") try: if all_pixels: xstart = 0 ystart = 0 - xend = naxis1 # full x size + xend = naxis1 # full x size yend = naxis2*2 # full y size with fits.open(imagename) as hdu: - uvis2_sci = hdu["SCI",1].data + uvis2_sci = hdu["SCI", 1].data uvis2_err = hdu[2].data uvis2_dq = hdu[3].data - uvis1_sci = hdu["SCI",2].data + uvis1_sci = hdu["SCI", 2].data uvis1_err = hdu[5].data uvis1_dq = hdu[6].data try: - fullsci = np.concatenate([uvis2_sci,uvis1_sci]) - fulldq = np.concatenate([uvis2_dq,uvis1_dq]) - fullerr = np.concatenate([uvis2_err,uvis1_err]) + fullsci = np.concatenate([uvis2_sci, uvis1_sci]) + fulldq = np.concatenate([uvis2_dq, uvis1_dq]) + fullerr = np.concatenate([uvis2_err, uvis1_err]) - fullsci = fullsci[ystart:yend,xstart:xend] - fulldq = fulldq[ystart:yend,xstart:xend] - fullerr = fullerr[ystart:yend,xstart:xend] + fullsci = fullsci[ystart:yend, xstart:xend] + fulldq = fulldq[ystart:yend, xstart:xend] + fullerr = fullerr[ystart:yend, xstart:xend] make1x3plot(scaling, colormaps, fullsci, fullerr, fulldq, xstart, xend, ystart, yend, @@ -185,26 +183,26 @@ def display_image(filename, figsize, dpi) except ValueError: - fullsci = np.concatenate([uvis2_sci,uvis1_sci]) - fullsci = fullsci[ystart:yend,xstart:xend] + fullsci = np.concatenate([uvis2_sci, uvis1_sci]) + fullsci = fullsci[ystart:yend, xstart:xend] - z1_sci, z2_sci = get_scale_limits(scaling[0],fullsci,'SCI') + z1_sci, z2_sci = get_scale_limits(scaling[0], fullsci, 'SCI') - fig, ax1 = plt.subplots(1,1,figsize=figsize,dpi=dpi) - im1 = ax1.imshow(fullsci,origin='lower',extent=(xstart,xend,ystart,yend),cmap=colormaps[0],vmin=z1_sci, vmax=z2_sci) + fig, ax1 = plt.subplots(1, 1, figsize=figsize, dpi=dpi) + im1 = ax1.imshow(fullsci, origin='lower', extent=(xstart, xend, ystart, yend), cmap=colormaps[0], vmin=z1_sci, vmax=z2_sci) if len(fname) > 18: ax1.set_title(f"WFC3/{detector} {fname}\n{h1['extname']} ext") else: ax1.set_title(f"WFC3/{detector} {fname} {h1['extname']} ext") - fig.colorbar(im1, ax=ax1,shrink=.75,pad=.03) + fig.colorbar(im1, ax=ax1, shrink=.75, pad=.03) - except (IndexError,KeyError): + except (IndexError, KeyError): if all_pixels: - xstart = 0 - ystart = 0 - xend = naxis1 # full x size - yend = naxis2 # full y size + xstart = 0 + ystart = 0 + xend = naxis1 # full x size + yend = naxis2 # full y size with fits.open(imagename) as hdu: uvis_ext1 = hdu[1].data @@ -212,35 +210,34 @@ def display_image(filename, uvis_ext3 = hdu[3].data try: - uvis_ext1 = uvis_ext1[ystart:yend,xstart:xend] - uvis_ext2 = uvis_ext2[ystart:yend,xstart:xend] - uvis_ext3 = uvis_ext3[ystart:yend,xstart:xend] + uvis_ext1 = uvis_ext1[ystart:yend, xstart:xend] + uvis_ext2 = uvis_ext2[ystart:yend, xstart:xend] + uvis_ext3 = uvis_ext3[ystart:yend, xstart:xend] make1x3plot(scaling, colormaps, uvis_ext1, uvis_ext2, uvis_ext3, xstart, xend, ystart, yend, detector, fname, h1, h2, h3, figsize, dpi) - except (TypeError,IndexError,AttributeError): + except (TypeError, IndexError, AttributeError): - z1_sci, z2_sci = get_scale_limits(scaling[0],uvis_ext1,'SCI') - fig, ax1 = plt.subplots(1,1,figsize=figsize,dpi=dpi) - im1 = ax1.imshow(uvis_ext1,origin='lower',extent=(xstart,xend,ystart,yend),cmap=colormaps[0],vmin=z1_sci, vmax=z2_sci) + z1_sci, z2_sci = get_scale_limits(scaling[0], uvis_ext1, 'SCI') + fig, ax1 = plt.subplots(1, 1, figsize=figsize, dpi=dpi) + im1 = ax1.imshow(uvis_ext1, origin='lower', extent=(xstart, xend, ystart, yend), cmap=colormaps[0], vmin=z1_sci, vmax=z2_sci) if len(fname) > 18: ax1.set_title(f"WFC3/{detector} {fname}\n{h1['extname']} ext") else: ax1.set_title(f"WFC3/{detector} {fname} {h1['extname']} ext") - fig.colorbar(im1, ax=ax1,shrink=.75,pad=.03) - + fig.colorbar(im1, ax=ax1, shrink=.75, pad=.03) if detector == 'IR' and '_ima.fits' not in fname: - if ima_multiread == True: + if ima_multiread is True: sys.exit("keyword argument 'ima_multiread' can only be set to True for 'ima.fits' files") if all_pixels: xstart = 0 ystart = 0 - xend = naxis1 # full x size - yend = naxis2 # full y size + xend = naxis1 # full x size + yend = naxis2 # full y size try: with fits.open(imagename) as hdu: @@ -248,9 +245,9 @@ def display_image(filename, data_err = hdu[2].data data_dq = hdu[3].data - data_sci = data_sci[ystart:yend,xstart:xend] - data_err = data_err[ystart:yend,xstart:xend] - data_dq = data_dq[ystart:yend,xstart:xend] + data_sci = data_sci[ystart:yend, xstart:xend] + data_err = data_err[ystart:yend, xstart:xend] + data_dq = data_dq[ystart:yend, xstart:xend] make1x3plot(scaling, colormaps, data_sci, data_err, data_dq, xstart, xend, ystart, yend, @@ -258,49 +255,48 @@ def display_image(filename, figsize, dpi) except (AttributeError, TypeError, ValueError): - z1_sci, z2_sci = get_scale_limits(scaling[0],data_sci,'SCI') - fig, ax1 = plt.subplots(1,1,figsize=figsize,dpi=dpi) - im1 = ax1.imshow(data_sci,origin='lower',extent=(xstart,xend,ystart,yend),cmap=colormaps[0],vmin=z1_sci, vmax=z2_sci) - if len(fname) > 18: - ax1.set_title(f"WFC3/{detector} {fname}\n{h1['extname']} ext") - else: - ax1.set_title(f"WFC3/{detector} {fname} {h1['extname']} ext") - fig.colorbar(im1, ax=ax1,shrink=.75,pad=.03) - + z1_sci, z2_sci = get_scale_limits(scaling[0], data_sci, 'SCI') + fig, ax1 = plt.subplots(1, 1, figsize=figsize, dpi=dpi) + im1 = ax1.imshow(data_sci, origin='lower', extent=(xstart, xend, ystart, yend), cmap=colormaps[0], vmin=z1_sci, vmax=z2_sci) + if len(fname) > 18: + ax1.set_title(f"WFC3/{detector} {fname}\n{h1['extname']} ext") + else: + ax1.set_title(f"WFC3/{detector} {fname} {h1['extname']} ext") + fig.colorbar(im1, ax=ax1, shrink=.75, pad=.03) if '_ima.fits' in fname: if all_pixels: xstart = 0 ystart = 0 - xend = naxis1 # full x size - yend = naxis2 # full y size + xend = naxis1 # full x size + yend = naxis2 # full y size - if ima_multiread == True: + if ima_multiread is True: nsamps = h['NSAMP'] - for ext in reversed(range(1,nsamps+1)): + for ext in reversed(range(1, nsamps+1)): with fits.open(imagename) as hdu: - data_sci = hdu['SCI',ext].data - data_err = hdu['ERR',ext].data - data_dq = hdu['DQ',ext].data + data_sci = hdu['SCI', ext].data + data_err = hdu['ERR', ext].data + data_dq = hdu['DQ', ext].data - data_sci = data_sci[ystart:yend,xstart:xend] - data_err = data_err[ystart:yend,xstart:xend] - data_dq = data_dq[ystart:yend,xstart:xend] + data_sci = data_sci[ystart:yend, xstart:xend] + data_err = data_err[ystart:yend, xstart:xend] + data_dq = data_dq[ystart:yend, xstart:xend] makeIR1x3plot(scaling, colormaps, data_sci, data_err, data_dq, - xstart, xend, ystart, yend, - detector, fname, h1, h2, h3, nsamps, ext, - figsize, dpi) + xstart, xend, ystart, yend, + detector, fname, h1, h2, h3, nsamps, ext, + figsize, dpi) - if ima_multiread == False: + if ima_multiread is False: with fits.open(imagename) as hdu: - data_sci = hdu['SCI',1].data - data_err = hdu['ERR',1].data - data_dq = hdu['DQ',1].data + data_sci = hdu['SCI', 1].data + data_err = hdu['ERR', 1].data + data_dq = hdu['DQ', 1].data - data_sci = data_sci[ystart:yend,xstart:xend] - data_err = data_err[ystart:yend,xstart:xend] - data_dq = data_dq[ystart:yend,xstart:xend] + data_sci = data_sci[ystart:yend, xstart:xend] + data_err = data_err[ystart:yend, xstart:xend] + data_dq = data_dq[ystart:yend, xstart:xend] make1x3plot(scaling, colormaps, data_sci, data_err, data_dq, xstart, xend, ystart, yend, @@ -308,37 +304,9 @@ def display_image(filename, figsize, dpi) -def get_bunit(ext1header): - """ Get the brightness unit for the plot axis label - - Parameters - ---------- - ext1header: Header - The extension 1 header of the fits file being displayed. This is the - extension that contains the brightness unit keyword - - Returns - ------- - The string of the brightness unit for the axis label - {'counts', 'counts/s','e$^-$', 'e$^-$/s'} - - """ - units = ext1header['bunit'] - - if units == 'COUNTS': - return 'counts' - elif units == 'COUNTS/S': - return 'counts/s' - elif units == 'ELECTRONS': - return 'e$^-$' - elif units == 'ELECTRONS/S': - return 'e$^-$/s' - else: - return units - - def get_scale_limits(scaling, array, extname): - """ Get the scale limits to use for the image extension being displayed + """ + Get the scale limits to use for the image extension being displayed. Parameters ---------- @@ -346,8 +314,8 @@ def get_scale_limits(scaling, array, extname): List of real numbers to act as scalings for the SCI, ERR, and DQ arrays. The first element in the list is for the SCI array the second is for the ERR array and the third element in the list is for the DQ extension. If - no scalings are given the default scaling will use - ginga.util.zscale.zscale(). All three scalings must be provided even if + no scalings are given the default scaling will use astropy.visualization + ZScaleInterval.get_limits(). All three scalings must be provided even if only changing 1-2 scalings. E.g. to change SCI array scaling: scaling = [(5E4,8E4),(None,None),(None,None)] @@ -355,40 +323,42 @@ def get_scale_limits(scaling, array, extname): The ImageHDU array that is being displayed. extname: String {"SCI", "ERR", "DQ"} - The name of the extension of which the scale is being determined + The name of the extension of which the scale is being determined. Returns ------- z1: Float - The minimum value for the image scale + The minimum value for the image scale. z2: Float - The maximum value for the image scale + The maximum value for the image scale. """ + + z = ZScaleInterval() if extname == 'DQ': - if scaling[0] == None and scaling[1] == None: + if scaling[0] is None and scaling[1] is None: z1, z2 = array.min(), array.max() - elif scaling[0] == None and scaling[1] != None: + elif scaling[0] is None and scaling[1] is not None: z1 = array.min() z2 = scaling[1] - elif scaling[0] != None and scaling[1] == None: + elif scaling[0] is not None and scaling[1] is None: z1 = scaling[0] z2 = array.max() - elif scaling[0] != None and scaling[1] != None: + elif scaling[0] is not None and scaling[1] is not None: z1 = scaling[0] z2 = scaling[1] - + elif extname == 'SCI' or extname == 'ERR': - if scaling[0] == None and scaling[1] == None: - z1, z2 = zscale.zscale(array) - elif scaling[0] == None and scaling[1] != None: - z1 = zscale.zscale(array)[0] + if scaling[0] is None and scaling[1] is None: + z1, z2 = z.get_limits(array) + elif scaling[0] is None and scaling[1] is not None: + z1 = z.get_limits(array)[0] z2 = scaling[1] - elif scaling[0] != None and scaling[1] == None: + elif scaling[0] is not None and scaling[1] is None: z1 = scaling[0] - z2 = zscale.zscale(array)[1] - elif scaling[0] != None and scaling[1] != None: + z2 = z.get_limits(array)[1] + elif scaling[0] is not None and scaling[1] is not None: z1 = scaling[0] z2 = scaling[1] else: @@ -401,8 +371,8 @@ def get_scale_limits(scaling, array, extname): def make1x3plot(scaling, colormaps, fullsci, fullerr, fulldq, xstart, xend, ystart, yend, detector, fname, h1, h2, h3, - figsize, dpi): - """ Make a 3 column figure to display any WFC3 image or image section + figsize=(9, 6), dpi=100): + """ Make a 3 column figure to display any WFC3 image or image section. Parameters ---------- @@ -410,8 +380,8 @@ def make1x3plot(scaling, colormaps, fullsci, fullerr, fulldq, List of real numbers to act as scalings for the SCI, ERR, and DQ arrays. The first element in the list is for the SCI array the second is for the ERR array and the third element in the list is for the DQ extension. If - no scalings are given the default scaling will use - ginga.util.zscale.zscale(). All three scalings must be provided even if + no scalings are given the default scaling will use astropy.visualization + ZScaleInterval.get_limits(). All three scalings must be provided even if only changing 1-2 scalings. E.g. to change SCI array scaling: scaling = [(5E4,8E4),(None,None),(None,None)] @@ -451,10 +421,10 @@ def make1x3plot(scaling, colormaps, fullsci, fullerr, fulldq, The ending index value for the y-axis of the image. detector: String {"UVIS", "IR"} - The detector used for the image + The detector used for the image. fname: String - The name of the file being plotted + The name of the file being plotted. h1: Header The extension 1 header of the fits file being displayed. @@ -466,10 +436,10 @@ def make1x3plot(scaling, colormaps, fullsci, fullerr, fulldq, The extension 3 header of the fits file being displayed. figsize: (float,float) - The width, height of the figure. Default is (9,6) + The width, height of the figure. Default is (9,6). dpi: float - The resolution of the figure in dots-per-inch. Default is 100 + The resolution of the figure in dots-per-inch. Default is 100. Returns ------- @@ -477,15 +447,15 @@ def make1x3plot(scaling, colormaps, fullsci, fullerr, fulldq, """ - z1_sci, z2_sci = get_scale_limits(scaling[0],fullsci,'SCI') - z1_err, z2_err = get_scale_limits(scaling[1],fullerr,'ERR') - z1_dq, z2_dq = get_scale_limits(scaling[2],fulldq,'DQ') + z1_sci, z2_sci = get_scale_limits(scaling[0], fullsci, 'SCI') + z1_err, z2_err = get_scale_limits(scaling[1], fullerr, 'ERR') + z1_dq, z2_dq = get_scale_limits(scaling[2], fulldq, 'DQ') - fig, [ax1,ax2,ax3] = plt.subplots(1,3,figsize=figsize,dpi=dpi) + fig, [ax1, ax2, ax3] = plt.subplots(1, 3, figsize=figsize, dpi=dpi) - im1 = ax1.imshow(fullsci,origin='lower',extent=(xstart,xend,ystart,yend),cmap=colormaps[0],vmin=z1_sci, vmax=z2_sci) - im2 = ax2.imshow(fullerr,origin='lower',extent=(xstart,xend,ystart,yend),cmap=colormaps[1],vmin=z1_err, vmax=z2_err) - im3 = ax3.imshow(fulldq, origin='lower',extent=(xstart,xend,ystart,yend),cmap=colormaps[2],vmin=z1_dq, vmax=z2_dq) + im1 = ax1.imshow(fullsci, origin='lower', extent=(xstart, xend, ystart, yend), cmap=colormaps[0], vmin=z1_sci, vmax=z2_sci) + im2 = ax2.imshow(fullerr, origin='lower', extent=(xstart, xend, ystart, yend), cmap=colormaps[1], vmin=z1_err, vmax=z2_err) + im3 = ax3.imshow(fulldq, origin='lower', extent=(xstart, xend, ystart, yend), cmap=colormaps[2], vmin=z1_dq, vmax=z2_dq) if len(fname) > 18: ax1.set_title(f"WFC3/{detector} {fname}\n{h1['extname']} ext") @@ -495,15 +465,16 @@ def make1x3plot(scaling, colormaps, fullsci, fullerr, fulldq, ax1.set_title(f"WFC3/{detector} {fname} {h1['extname']} ext") ax2.set_title(f"WFC3/{detector} {fname} {h2['extname']} ext") ax3.set_title(f"WFC3/{detector} {fname} {h3['extname']} ext") - fig.colorbar(im1, ax=ax1,shrink=.25,pad=.03) - fig.colorbar(im2, ax=ax2,shrink=.25,pad=.03) - fig.colorbar(im3, ax=ax3,shrink=.25,pad=.03) + fig.colorbar(im1, ax=ax1, shrink=.25, pad=.03) + fig.colorbar(im2, ax=ax2, shrink=.25, pad=.03) + fig.colorbar(im3, ax=ax3, shrink=.25, pad=.03) + def makeIR1x3plot(scaling, colormaps, data_sci, data_err, data_dq, xstart, xend, ystart, yend, detector, fname, h1, h2, h3, nsamps, ext, - figsize, dpi): - """ Make a 3 column figure to display any WFC3 IMA image or image section + figsize=(9, 6), dpi=100): + """ Make a 3 column figure to display any WFC3 IMA image or image section. Parameters ---------- @@ -511,8 +482,8 @@ def makeIR1x3plot(scaling, colormaps, data_sci, data_err, data_dq, List of real numbers to act as scalings for the SCI, ERR, and DQ arrays. The first element in the list is for the SCI array the second is for the ERR array and the third element in the list is for the DQ extension. If - no scalings are given the default scaling will use - ginga.util.zscale.zscale(). All three scalings must be provided even if + no scalings are given the default scaling will use astropy.visualization + ZScaleInterval.get_limits(). All three scalings must be provided even if only changing 1-2 scalings. E.g. to change SCI array scaling: scaling = [(5E4,8E4),(None,None),(None,None)] @@ -552,10 +523,10 @@ def makeIR1x3plot(scaling, colormaps, data_sci, data_err, data_dq, The ending index value for the y-axis of the image. detector: String {"UVIS", "IR"} - The detector used for the image + The detector used for the image. fname: String - The name of the file being plotted + The name of the file being plotted. h1: Header The extension 1 header of the fits file being displayed. @@ -567,16 +538,16 @@ def makeIR1x3plot(scaling, colormaps, data_sci, data_err, data_dq, The extension 3 header of the fits file being displayed. nsamps: Integer - The number of samples (readouts) contained in the file + The number of samples (readouts) contained in the file. ext: Integer - The extension to be displayed. Ranges from 1 to nsamp + The extension to be displayed. Ranges from 1 to nsamp. figsize: (float,float) - The width, height of the figure. Default is (9,6) + The width, height of the figure. Default is (9,6). dpi: float - The resolution of the figure in dots-per-inch. Default is 100 + The resolution of the figure in dots-per-inch. Default is 100. Returns ------- @@ -584,17 +555,17 @@ def makeIR1x3plot(scaling, colormaps, data_sci, data_err, data_dq, """ - z1_sci, z2_sci = get_scale_limits(scaling[0],data_sci,'SCI') - z1_err, z2_err = get_scale_limits(scaling[1],data_err,'ERR') - z1_dq, z2_dq = get_scale_limits(scaling[2],data_dq,'DQ') - - fig, [ax1,ax2,ax3] = plt.subplots(1,3,figsize = figsize,dpi=dpi) - im1 = ax1.imshow(data_sci,origin='lower',extent=(xstart,xend,ystart,yend),cmap=colormaps[0],vmin=z1_sci, vmax=z2_sci) - im2 = ax2.imshow(data_err,origin='lower',extent=(xstart,xend,ystart,yend),cmap=colormaps[1],vmin=z1_err, vmax=z2_err) - im3 = ax3.imshow(data_dq, origin='lower',extent=(xstart,xend,ystart,yend),cmap=colormaps[2],vmin=z1_dq, vmax=z2_dq) - fig.colorbar(im1, ax=ax1,shrink=.25,pad=.03) - fig.colorbar(im2, ax=ax2,shrink=.25,pad=.03) - fig.colorbar(im3, ax=ax3,shrink=.25,pad=.03) + z1_sci, z2_sci = get_scale_limits(scaling[0], data_sci, 'SCI') + z1_err, z2_err = get_scale_limits(scaling[1], data_err, 'ERR') + z1_dq, z2_dq = get_scale_limits(scaling[2], data_dq, 'DQ') + + fig, [ax1, ax2, ax3] = plt.subplots(1, 3, figsize=figsize, dpi=dpi) + im1 = ax1.imshow(data_sci, origin='lower', extent=(xstart, xend, ystart, yend), cmap=colormaps[0], vmin=z1_sci, vmax=z2_sci) + im2 = ax2.imshow(data_err, origin='lower', extent=(xstart, xend, ystart, yend), cmap=colormaps[1], vmin=z1_err, vmax=z2_err) + im3 = ax3.imshow(data_dq, origin='lower', extent=(xstart, xend, ystart, yend), cmap=colormaps[2], vmin=z1_dq, vmax=z2_dq) + fig.colorbar(im1, ax=ax1, shrink=.25, pad=.03) + fig.colorbar(im2, ax=ax2, shrink=.25, pad=.03) + fig.colorbar(im3, ax=ax3, shrink=.25, pad=.03) if len(fname) > 18: ax1.set_title(f"WFC3/{detector} {fname}\n {h1['extname']} read {(nsamps+1)-ext}") diff --git a/notebooks/WFC3/image_displayer_analyzer/requirements.txt b/notebooks/WFC3/image_displayer_analyzer/requirements.txt index a624b7053..65f7c3c7c 100644 --- a/notebooks/WFC3/image_displayer_analyzer/requirements.txt +++ b/notebooks/WFC3/image_displayer_analyzer/requirements.txt @@ -1,2 +1,6 @@ -astroquery==0.4.6 -matplotlib==3.7.0 +astropy +astroquery +jupyter +matplotlib +numpy +scipy diff --git a/notebooks/WFC3/image_displayer_analyzer/row_column_stats.py b/notebooks/WFC3/image_displayer_analyzer/row_column_stats.py index da71d38e3..d26b619fc 100755 --- a/notebooks/WFC3/image_displayer_analyzer/row_column_stats.py +++ b/notebooks/WFC3/image_displayer_analyzer/row_column_stats.py @@ -1,5 +1,4 @@ #! /usr/bin/env python - import sys import numpy as np @@ -7,6 +6,7 @@ import matplotlib.pyplot as plt from scipy.stats import mode as mode + def get_bunit(ext1header): """ Get the brightness unit for the plot axis label @@ -35,6 +35,7 @@ def get_bunit(ext1header): else: return units + def get_yaxis_and_label(stat, scidata, axes): """ Get the y-axis values and the y axis label for the plot @@ -78,8 +79,9 @@ def get_yaxis_and_label(stat, scidata, axes): return yaxis, ylabel + def makeplot(xaxis, yaxis, axlabel, ylabel, - bunit,detector, fname, h1, ylim, + bunit, detector, fname, h1, ylim, figsize, dpi): """ Make and display the plot for WFC3 UVIS or IR images @@ -121,26 +123,26 @@ def makeplot(xaxis, yaxis, axlabel, ylabel, N/A """ - fig, ax1 = plt.subplots(1, 1, figsize = figsize, dpi=dpi) - # ax1.scatter(xaxis,yaxis,10,alpha=0.75) - ax1.plot(xaxis,yaxis,marker='o',markersize=5,ls='-',alpha=0.75) + fig, ax1 = plt.subplots(1, 1, figsize=figsize, dpi=dpi) + ax1.plot(xaxis, yaxis, marker='o', markersize=5, ls='-', alpha=0.75) - ax1.set_xlabel(f"{axlabel} Number",size=13) - ax1.set_ylabel(f"{axlabel} {ylabel} [{bunit}]",size=13) + ax1.set_xlabel(f"{axlabel} Number", size=13) + ax1.set_ylabel(f"{axlabel} {ylabel} [{bunit}]", size=13) ax1.grid(alpha=.75) ax1.minorticks_on() - ax1.yaxis.set_ticks_position('both'),ax1.xaxis.set_ticks_position('both') - ax1.tick_params(axis='both',which='minor',direction='in',labelsize = 12,length=4) - ax1.tick_params(axis='both',which='major',direction='in',labelsize = 12,length=7) + ax1.yaxis.set_ticks_position('both'), ax1.xaxis.set_ticks_position('both') + ax1.tick_params(axis='both', which='minor', direction='in', labelsize=12, length=4) + ax1.tick_params(axis='both', which='major', direction='in', labelsize=12, length=7) if len(fname) > 18: - ax1.set_title(f"WFC3/{detector} {fname}\n {h1['extname']} ext",size=14) + ax1.set_title(f"WFC3/{detector} {fname}\n {h1['extname']} ext", size=14) else: - ax1.set_title(f"WFC3/{detector} {fname} {h1['extname']} ext",size=14) - if ylim != None: - ax1.set_ylim(ylim[0],ylim[1]) + ax1.set_title(f"WFC3/{detector} {fname} {h1['extname']} ext", size=14) + if ylim is not None: + ax1.set_ylim(ylim[0], ylim[1]) + def make_ima_plot(xaxis, yaxis, axlabel, ylabel, - bunit, detector, fname,h1, ylim, nsamps, ext, + bunit, detector, fname, h1, ylim, nsamps, ext, figsize, dpi): """ Make and display the plot for WFC3 IR IMA images @@ -188,27 +190,27 @@ def make_ima_plot(xaxis, yaxis, axlabel, ylabel, N/A """ - fig, ax1 = plt.subplots(1,1,figsize=figsize,dpi=dpi) - # ax1.scatter(xaxis,yaxis,10,alpha=0.75) - ax1.plot(xaxis,yaxis,marker='o',markersize=5,ls='-',alpha=0.75) + fig, ax1 = plt.subplots(1, 1, figsize=figsize, dpi=dpi) + ax1.plot(xaxis, yaxis, marker='o', markersize=5, ls='-', alpha=0.75) - ax1.set_xlabel(f"{axlabel} Number",size=13) - ax1.set_ylabel(f"{axlabel} {ylabel} [{bunit}]",size=13) + ax1.set_xlabel(f"{axlabel} Number", size=13) + ax1.set_ylabel(f"{axlabel} {ylabel} [{bunit}]", size=13) ax1.grid(alpha=.75) ax1.minorticks_on() - ax1.yaxis.set_ticks_position('both'),ax1.xaxis.set_ticks_position('both') - ax1.tick_params(axis='both',which='minor',direction='in',labelsize = 12,length=4) - ax1.tick_params(axis='both',which='major',direction='in',labelsize = 12,length=7) + ax1.yaxis.set_ticks_position('both'), ax1.xaxis.set_ticks_position('both') + ax1.tick_params(axis='both', which='minor', direction='in', labelsize=12, length=4) + ax1.tick_params(axis='both', which='major', direction='in', labelsize=12, length=7) if len(fname) > 18: - ax1.set_title(f"WFC3/{detector} {fname}\n {h1['extname']} read {(nsamps+1)-ext}",size=14) + ax1.set_title(f"WFC3/{detector} {fname}\n {h1['extname']} read {(nsamps+1)-ext}", size=14) else: - ax1.set_title(f"WFC3/{detector} {fname} {h1['extname']} read {(nsamps+1)-ext}",size=14) - if ylim != None: - ax1.set_ylim(ylim[0],ylim[1]) + ax1.set_title(f"WFC3/{detector} {fname} {h1['extname']} read {(nsamps+1)-ext}", size=14) + if ylim is not None: + ax1.set_ylim(ylim[0], ylim[1]) -def row_column_stats(filename, stat='median', axis='column', ylim=(None,None), + +def row_column_stats(filename, stat='median', axis='column', ylim=(None, None), printmeta=False, ima_multiread=False, plot=True, - figsize=(9,6), dpi=120): + figsize=(9, 6), dpi=120): """ A function to plot the column median vs column number for the 'SCI' data of any WFC3 fits image. @@ -296,7 +298,7 @@ def row_column_stats(filename, stat='median', axis='column', ylim=(None,None), print("Invalid image section specified") return 0, 0 try: - xstart = int(xsec[: xs]) + xstart = int(xsec[:xs]) except ValueError: print("Problem getting xstart") return @@ -351,69 +353,66 @@ def row_column_stats(filename, stat='median', axis='column', ylim=(None,None), sys.exit("keyword argument 'axis' must be set to 'column' or 'row' ") if printmeta: - print(f"\t{si}/{detector} {fname} ") + print(f"\t{si}/{detector} {fname}") print('-'*44) print(f"Filter = {h['filter']}, Date-Obs = {h['date-obs']} T{h['time-obs']},\nTarget = {h['targname']}, Exptime = {h['exptime']}, Subarray = {issubarray}, Units = {h1['bunit']}\n") - - if detector == 'UVIS': - if ima_multiread == True: + if ima_multiread is True: sys.exit("keyword argument 'ima_multiread' can only be set to True for 'ima.fits' files") try: with fits.open(imagename) as hdu: - uvis1_sci = hdu['SCI',2].data - uvis2_sci = hdu['SCI',1].data + uvis1_sci = hdu['SCI', 2].data + uvis2_sci = hdu['SCI', 1].data - uvis_sci = np.concatenate([uvis2_sci,uvis1_sci]) + uvis_sci = np.concatenate([uvis2_sci, uvis1_sci]) if all_pixels: - uvis_sci = uvis_sci[ystart:yend*2,xstart:xend] + uvis_sci = uvis_sci[ystart:yend*2, xstart:xend] if axis == 'row': xaxis = range(ystart, yend*2) else: - uvis_sci = uvis_sci[ystart:yend,xstart:xend] + uvis_sci = uvis_sci[ystart:yend, xstart:xend] except KeyError: with fits.open(imagename) as hdu: - uvis_sci = hdu['SCI',1].data + uvis_sci = hdu['SCI', 1].data if all_pixels: - uvis_sci = uvis_sci[ystart:yend,xstart:xend] + uvis_sci = uvis_sci[ystart:yend, xstart:xend] if axis == 'row': xaxis = range(ystart, yend) else: - uvis_sci = uvis_sci[ystart:yend,xstart:xend] + uvis_sci = uvis_sci[ystart:yend, xstart:xend] - yaxis, ylabel = get_yaxis_and_label(stat,uvis_sci,axes) + yaxis, ylabel = get_yaxis_and_label(stat, uvis_sci, axes) if plot: makeplot(xaxis, yaxis, axlabel, ylabel, bunit, detector, fname, h1, ylim, figsize, dpi) - if detector == 'IR': - if ima_multiread == True: + if ima_multiread is True: nsamps = fits.getheader(imagename)['NSAMP'] - for ext in reversed(range(1,nsamps+1)): + for ext in reversed(range(1, nsamps+1)): with fits.open(imagename) as hdu: - scidata = hdu['SCI',ext].data + scidata = hdu['SCI', ext].data - scidata = scidata[ystart:yend,xstart:xend] + scidata = scidata[ystart:yend, xstart:xend] - yaxis, ylabel = get_yaxis_and_label(stat,scidata,axes) + yaxis, ylabel = get_yaxis_and_label(stat, scidata, axes) if plot: make_ima_plot(xaxis, yaxis, axlabel, ylabel, - bunit, detector, fname,h1, ylim, + bunit, detector, fname, h1, ylim, nsamps, ext, figsize, dpi) - if ima_multiread == False: + if ima_multiread is False: with fits.open(imagename) as hdu: - scidata = hdu['SCI',1].data + scidata = hdu['SCI', 1].data - scidata = scidata[ystart:yend,xstart:xend] + scidata = scidata[ystart:yend, xstart:xend] - yaxis, ylabel = get_yaxis_and_label(stat,scidata,axes) + yaxis, ylabel = get_yaxis_and_label(stat, scidata, axes) if plot: makeplot(xaxis, yaxis, axlabel, ylabel, bunit, detector, fname, h1, diff --git a/notebooks/WFC3/image_displayer_analyzer/wfc3_image_displayer_analyzer.ipynb b/notebooks/WFC3/image_displayer_analyzer/wfc3_image_displayer_analyzer.ipynb index aa95e3e0b..06ed259e1 100755 --- a/notebooks/WFC3/image_displayer_analyzer/wfc3_image_displayer_analyzer.ipynb +++ b/notebooks/WFC3/image_displayer_analyzer/wfc3_image_displayer_analyzer.ipynb @@ -8,6 +8,8 @@ "# WFC3 Image Displayer & Analyzer \n", "***\n", "## Learning Goals\n", + "This notebook provides a method to quickly display images from the Hubble Space Telescope’s Wide Field
\n", + "Camera 3 (WFC3) instrument. This tool also allows the user to derive statistics by row or column in the image.
\n", "\n", "By the end of this tutorial, you will:\n", "\n", @@ -15,14 +17,11 @@ "- Learn how to use the `display_image` tool to display any WFC3 fits file.\n", "- Learn how to use the `row_column_stats` tool to plot row or column statistics for any WFC3 fits file.\n", "\n", - "This notebook provides a method to quickly display images from the Hubble Space Telescope’s Wide Field Camera 3 (WFC3) instrument. This tool also allows the user to derive statistics by row or column in the image.
\n", - "Please make sure you have read the `README.md` file before continuing. \n", - "\n", "## Table of Contents\n", " [Introduction](#intro)
\n", " [1. Imports](#imports)
\n", " [2. Query MAST and download a WFC3 `flt.fits` and `ima.fits` image](#download)
\n", - " [3. display_image](#display)
\n", + " [3. `display_image`](#display)
\n", "       [3.1 Display the full images with metadata](#displayfull)
\n", "       [3.2 Display UVIS1 & UVIS2 separately](#perchip)
\n", "       [3.3 Display an image section and change the `SCI` array colormap](#colormap)
\n", @@ -81,17 +80,18 @@ "\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 and activated a virtual environment using the \n", + " requirements file in this notebook's repository. Please make sure you have read the contents of the README file before continuing the notebook.
\n", "\n", "We import:
\n", - "
\n", - "**•** *os* for setting environment variables
\n", - " \n", - "**•** *astroquery.mast Observations* for downloading data from MAST
\n", - "**•** *matplotlib.pyplot* for plotting data\n", - " \n", - "**•** *display_image* for displaying a WFC3 image
\n", - "**•** *row_column_stats* for computing statistics on a WFC3 image" + "\n", + "| Package Name | Purpose |\n", + "|:--------------------------------|:-------------------------------------|\n", + "| `os` | setting environment variables |\n", + "| `astroquery.mast.Observations` | downloading data from MAST |\n", + "| `matplotlib.pyplot` | plotting data |\n", + "| `display_image` | displaying any WFC3 image |\n", + "| `row_column_stats` | computing statistics on a WFC3 image |" ] }, { @@ -119,11 +119,12 @@ "## 2. Query MAST and download a WFC3 `flt.fits` and `ima.fits` image \n", "You may download the data from MAST using either the [Archive Search Engine](https://archive.stsci.edu/hst/search.php) or the [MAST Portal](https://mast.stsci.edu/portal/Mashup/Clients/Mast/Portal.html).\n", "\n", - "Here, we download our images via `astroquery`. For more information, please look at the documentation for [Astroquery](https://astroquery.readthedocs.io/en/latest/),\n", - "[Astroquery.mast](https://astroquery.readthedocs.io/en/latest/mast/mast.html), and \n", + "Here, we download our images via `astroquery`. For more information, please look at the documentation for
\n", + "[Astroquery](https://astroquery.readthedocs.io/en/latest/), [Astroquery.mast](https://astroquery.readthedocs.io/en/latest/mast/mast.html), and \n", "[CAOM Field Descriptions](https://mast.stsci.edu/api/v0/_c_a_o_mfields.html), which is used for the `obs_table` variable.\n", "\n", - "We download images of N2525 from proposal 15145, one being a `flt.fits` in WFC3/UVIS and the other being a `ima.fits` in WFC3/IR. After downloading the images, we move them to our current working directory (cwd)." + "We download images of N2525 from proposal 15145, one being a `flt.fits` in WFC3/UVIS and the other
\n", + "being a `ima.fits` in WFC3/IR. After downloading the images, we move them to our current working directory (cwd)." ] }, { @@ -132,8 +133,8 @@ "metadata": {}, "outputs": [], "source": [ - "query = [('idgga5*','UVIS','FLT',(2,3)),\n", - " ('i*','IR','IMA',(10,11))]\n", + "query = [('idgga5*', 'UVIS', 'FLT', (2, 3)),\n", + " ('i*', 'IR', 'IMA', (10, 11))]\n", "\n", "for criteria in query:\n", " # Get the observation records\n", @@ -158,8 +159,7 @@ " os.rmdir('mastDownload/HST/'+filename[:9])\n", " \n", " os.rmdir('mastDownload/HST/')\n", - " os.rmdir('mastDownload/')\n", - " " + " os.rmdir('mastDownload/')" ] }, { @@ -184,7 +184,9 @@ "source": [ "\n", "## 3. `display_image`\n", - "In this section, we demonstrate the functionality of `display_image`, a useful tool for quickly analyzing WFC3 images. The subsections explain how to display full images with metadata, individual WFC3/UVIS chip images, a section of an image with various colormaps/scaling, and individual WFC3/IR `ima` reads." + "In this section, we demonstrate the functionality of `display_image`, a useful tool for quickly analyzing WFC3 images.
\n", + "The subsections explain how to display full images with metadata, individual WFC3/UVIS chip images, a section of an
\n", + "image with various colormaps/scaling, and individual WFC3/IR `ima` reads." ] }, { @@ -193,7 +195,10 @@ "source": [ "\n", "### 3.1 Display the full images with metadata\n", - "First, we display the `SCI`, `ERR`, and `DQ` arrays for each image and print header info. The default value for `printmeta` is `False`. In the cell below, we set the keyword `printmeta` to `True` to print useful information from the header of the file to the screen. The WFC3/UVIS image is in electrons and the WFC3/IR image is in electrons/second. See Section 2.2.3 of the [WFC3 Data Handbook](https://hst-docs.stsci.edu/wfc3dhb) for full descriptions of `SCI`, `ERR`, and `DQ` arrays." + "First, we display the `SCI`, `ERR`, and `DQ` arrays for each image and print header info. The default value for `printmeta`
\n", + "is `False`. In the cell below, we set the keyword `printmeta` to `True` to print useful information from the header of the
\n", + "file to the screen. The WFC3/UVIS image is in electrons and the WFC3/IR image is in electrons/second. See Section 2.2.3
\n", + "of the [WFC3 Data Handbook](https://hst-docs.stsci.edu/wfc3dhb) for full descriptions of `SCI`, `ERR`, and `DQ` arrays." ] }, { @@ -202,8 +207,8 @@ "metadata": {}, "outputs": [], "source": [ - "display_image('idgga5m1q_flt.fits',printmeta=True)\n", - "display_image('idggabk1q_ima.fits',printmeta=True)" + "display_image('idgga5m1q_flt.fits', printmeta=True)\n", + "display_image('idggabk1q_ima.fits', printmeta=True)" ] }, { @@ -212,8 +217,9 @@ "source": [ "\n", "### 3.2 Display UVIS1 & UVIS2 separately\n", - "Next, we display the WFC3/UVIS chips separately. To select a section of an image, append [xstart:xend,ystart:yend] to the image name as shown below.
\n", - "Notice how we need to specify the full axis range `[0:4096,0:2051]` and not simply just `[:,:2051]` as in standard `numpy` notation." + "Next, we display the WFC3/UVIS chips separately. To select a section of an image, append [xstart:xend,ystart:yend] to the
\n", + "image name as shown below. Notice how we need to specify the full axis range `[0:4096,0:2051]` and not simply just
\n", + "`[:,:2051]` as in standard `numpy` notation." ] }, { @@ -222,7 +228,7 @@ "metadata": {}, "outputs": [], "source": [ - "print ('Display UVIS1')\n", + "print('Display UVIS1')\n", "display_image('idgga5m1q_flt.fits[0:4096,2051:4102]') " ] }, @@ -232,7 +238,7 @@ "metadata": {}, "outputs": [], "source": [ - "print ('Display UVIS2')\n", + "print('Display UVIS2')\n", "display_image('idgga5m1q_flt.fits[0:4096,0:2051]') " ] }, @@ -242,7 +248,8 @@ "source": [ "\n", "### 3.3 Display an image section and change the `SCI` array colormap\n", - "Then, we display `SCI` arrays with a different colormap. Regardless of how many colormaps are being changed, all three colormaps must be provided. The elements of `colormaps` sequentially correspond with the `SCI`, `ERR`, and `DQ` arrays." + "Then, we display `SCI` arrays with a different colormap. Regardless of how many colormaps are being changed, all three
\n", + "colormaps must be provided. The elements of `colormaps` sequentially correspond with the `SCI`, `ERR`, and `DQ` arrays." ] }, { @@ -252,7 +259,7 @@ "outputs": [], "source": [ "display_image('idgga5m1q_flt.fits[3420:3575,2590:2770]',\n", - " colormaps = [\"viridis\",\"Greys_r\",\"inferno_r\"])" + " colormaps=[\"viridis\", \"Greys_r\", \"inferno_r\"])" ] }, { @@ -261,7 +268,10 @@ "source": [ "\n", "### 3.4 Change the scaling of the `SCI` and `ERR` arrays\n", - "Now, we change the scaling of the `SCI` and `ERR` arrays. Regardless of how many scalings are being changed, all three scalings must be provided. The elements of `scaling` sequentially correspond with the `SCI`, `ERR`, and `DQ` arrays. The default scaling value of `None` uses `ginga.util.zscale.zscale()` for scaling (see [documentation](https://ginga.readthedocs.io/en/stable/) for more information). " + "Now, we change the scaling of the `SCI` and `ERR` arrays. Regardless of how many scalings are being changed, all three
\n", + "scalings must be provided. The elements of `scaling` sequentially correspond with the `SCI`, `ERR`, and `DQ` arrays.
\n", + "The default scaling value of `None` uses `astropy.visualization.ZScaleInterval()` for scaling
\n", + "(see [documentation](https://docs.astropy.org/en/stable/api/astropy.visualization.ZScaleInterval.html) for more information). " ] }, { @@ -271,8 +281,8 @@ "outputs": [], "source": [ "display_image('idgga5m1q_flt.fits[3420:3575,2590:2770]',\n", - " colormaps = [\"viridis\",\"viridis\",\"inferno_r\"],\n", - " scaling = [(50000,80000),(None,400),(None,None)])" + " colormaps=[\"viridis\", \"viridis\", \"inferno_r\"],\n", + " scaling=[(50000, 80000), (None, 400), (None, None)])" ] }, { @@ -291,8 +301,8 @@ "outputs": [], "source": [ "display_image('idggabk1q_ima.fits[43:55,299:311]',\n", - " colormaps = [\"viridis\",\"Greys_r\",\"inferno_r\"],\n", - " scaling=[(2,18),(None,None),(None,None)],\n", + " colormaps=[\"viridis\", \"Greys_r\", \"inferno_r\"],\n", + " scaling=[(2, 18), (None, None), (None, None)],\n", " ima_multiread=True)" ] }, @@ -302,7 +312,9 @@ "source": [ "\n", "## 4. `row_column_stats`\n", - "In this section, we demonstrate the functionality of `row_column_stats`, a useful tool for quickly computing WFC3 statistics. The subsections explain how to compute row and column statistics for a full image, individual WFC3/UVIS chips, a section of an image, and individual `ima` reads. The row/column numbers are on the x-axis and the statistics are on the y-axis." + "In this section, we demonstrate the functionality of `row_column_stats`, a useful tool for quickly computing WFC3 statistics.
\n", + "The subsections explain how to compute row and column statistics for a full image, individual WFC3/UVIS chips, a section of
\n", + "an image, and individual `ima` reads. The row/column numbers are on the x-axis and the statistics are on the y-axis." ] }, { @@ -321,14 +333,14 @@ "outputs": [], "source": [ "# plot column median for the full image\n", - "x,y = row_column_stats('idgga5m1q_flt.fits',\n", - " stat='median',\n", - " axis='column')\n", + "x, y = row_column_stats('idgga5m1q_flt.fits',\n", + " stat='median',\n", + " axis='column')\n", "\n", "# plot column standard deviation for the full image\n", - "x,y = row_column_stats('idgga5m1q_flt.fits',\n", - " stat='stddev',\n", - " axis='column')" + "x, y = row_column_stats('idgga5m1q_flt.fits',\n", + " stat='stddev',\n", + " axis='column')" ] }, { @@ -348,22 +360,22 @@ "outputs": [], "source": [ "# get column median values for UVIS2 but don't plot \n", - "x2,y2 = row_column_stats('idgga5m1q_flt.fits[0:4096,0:2051]',\n", - " stat='median',\n", - " axis='column',\n", - " plot=False)\n", + "x2, y2 = row_column_stats('idgga5m1q_flt.fits[0:4096,0:2051]',\n", + " stat='median',\n", + " axis='column',\n", + " plot=False)\n", "\n", "# get column median values for UVIS1 but don't plot \n", - "x1,y1 = row_column_stats('idgga5m1q_flt.fits[0:4096,2051:4102]',\n", - " stat='median',\n", - " axis='column',\n", - " plot=False)\n", + "x1, y1 = row_column_stats('idgga5m1q_flt.fits[0:4096,2051:4102]',\n", + " stat='median',\n", + " axis='column',\n", + " plot=False)\n", "\n", "# overplot UVIS1 and UVIS2 data on one figure \n", - "plt.figure(figsize=(8,6),dpi=130)\n", + "plt.figure(figsize=(8, 6), dpi=130)\n", "plt.grid(alpha=.5)\n", - "plt.plot(x1,y1,marker='.',label='UVIS 1',color='k')\n", - "plt.plot(x2,y2,marker='.',label='UVIS 2',color='C3')\n", + "plt.plot(x1, y1, marker='.', label='UVIS 1', color='k')\n", + "plt.plot(x2, y2, marker='.', label='UVIS 2', color='C3')\n", "plt.title('WFC3/UVIS idgga5m1q_flt.fits')\n", "plt.xlabel('Column Number')\n", "plt.ylabel('Column Median [e-]')\n", @@ -390,14 +402,14 @@ "display_image('idgga5m1q_flt.fits[3420:3575,2590:2770]')\n", "\n", "# plot row mean for a section of the image\n", - "x,y= row_column_stats('idgga5m1q_flt.fits[3420:3575,2590:2770]',\n", - " stat='mean',\n", - " axis='row')\n", + "x, y = row_column_stats('idgga5m1q_flt.fits[3420:3575,2590:2770]',\n", + " stat='mean',\n", + " axis='row')\n", "\n", "# plot column mean for a section of the image\n", - "x,y= row_column_stats('idgga5m1q_flt.fits[3420:3575,2590:2770]',\n", - " stat='mean',\n", - " axis='column')" + "x, y = row_column_stats('idgga5m1q_flt.fits[3420:3575,2590:2770]',\n", + " stat='mean',\n", + " axis='column')" ] }, { @@ -421,16 +433,16 @@ "display_image('idgga5m1q_flt.fits[3420:3575,2590:2770]')\n", "\n", "# plot row mean for single source with custom yaxis limits\n", - "x,y= row_column_stats('idgga5m1q_flt.fits[3420:3575,2590:2770]',\n", - " stat='mean',\n", - " axis='row',\n", - " ylim=(y1,y2))\n", + "x, y = row_column_stats('idgga5m1q_flt.fits[3420:3575,2590:2770]',\n", + " stat='mean',\n", + " axis='row',\n", + " ylim=(y1, y2))\n", "\n", "# plot column mean for single source with custom yaxis limits\n", - "x,y= row_column_stats('idgga5m1q_flt.fits[3420:3575,2590:2770]',\n", - " stat='mean',\n", - " axis='column',\n", - " ylim=(y1,y2))" + "x, y = row_column_stats('idgga5m1q_flt.fits[3420:3575,2590:2770]',\n", + " stat='mean',\n", + " axis='column',\n", + " ylim=(y1, y2))" ] }, { @@ -453,10 +465,10 @@ "display_image('idggabk1q_ima.fits[43:55,299:311]')\n", "\n", "# plot column mean for section of ima\n", - "x,y = row_column_stats('idggabk1q_ima.fits[43:55,299:311]',\n", - " stat='mean',\n", - " axis='column',\n", - " ima_multiread=True)" + "x, y = row_column_stats('idggabk1q_ima.fits[43:55,299:311]',\n", + " stat='mean',\n", + " axis='column',\n", + " ima_multiread=True)" ] }, { @@ -510,18 +522,11 @@ "[Top of Page](#top)\n", "\"Space " ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -535,7 +540,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.5" + "version": "3.11.5" } }, "nbformat": 4,