From 50f82099032add5a22ddbde1075bfbec7d25908f Mon Sep 17 00:00:00 2001 From: dulude Date: Mon, 11 Dec 2023 10:55:09 -0500 Subject: [PATCH 01/13] DataDl.ipynb: removed centering from the rest of the images --- notebooks/COS/DataDl/DataDl.ipynb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/notebooks/COS/DataDl/DataDl.ipynb b/notebooks/COS/DataDl/DataDl.ipynb index 7dd57ae41..28642bef9 100644 --- a/notebooks/COS/DataDl/DataDl.ipynb +++ b/notebooks/COS/DataDl/DataDl.ipynb @@ -209,7 +209,7 @@ "* Are taken with the COS instrument, using the G160M grating and either the 1533 or the 1577 cenwave setting\n", "\n", "### Fig 1.2\n", - "
\"\"
" + "\"New" ] }, { @@ -219,7 +219,7 @@ "The above search results in the table shown in Figure 1.3. \n", "\n", "### Fig 1.3\n", - "
\"The
\n", + "\"The\n", "\n", "If you need to change some parameters in your search - for instance, to also find data from the G130M grating - click on \"Edit Search\" (Fig 1.3, red dashed box).\n", "\n", @@ -234,7 +234,7 @@ "Most COS spectra have preview images (simple plots of flux by wavelength) which can be viewed before downloading the data. Clicking the dataset name (Fig 1.3, blue dashed oval) will take you to a page which shows the preview image, as well as some basic information about the data and whether there were any known failures during the operation. An example of such a page is shown in Figure 1.4.\n", "\n", "### Fig 1.4\n", - "
\"The
" + "\"The" ] }, { @@ -244,10 +244,10 @@ "Returning to the results page shown in Fig 1.3 and clicking \"Download Data\" opens a window as shown in Figure 1.5. In this window you can search for filetypes using the search bar, and unselect/select all the data products shown in the filtered list (Fig 1.5, green circle). Clicking the \"Showing all filetypes\" box (Figure 1.5, red box) shows a drop-down (Figure 1.6) where you can choose to show/hide certain types of data such as the uncalibrated data. \n", "\n", "### Fig 1.5\n", - "
\"The
\n", + "\"The\n", "\n", "### Fig 1.6\n", - "
\"The
\n", + "\"The\n", "\n", "When all of your desired data products are checked, click \"Start Download\" (Fig 1.5, yellow dashed box). This will download a compressed \"zipped\" folder of all of your data, divided into subdirectories by the observation. Most operating systems can decompress these folders by default. For help decompressing the zipped files, you can follow these links for: [Windows](https://support.microsoft.com/en-us/windows/zip-and-unzip-files-8d28fa72-f2f9-712f-67df-f80cf89fd4e5) and [Mac](https://support.apple.com/guide/mac-help/zip-and-unzip-files-and-folders-on-mac-mchlp2528/mac). There are numerous ways to do this on Linux, however we have not vetted them." ] @@ -264,7 +264,7 @@ "\n", "### Fig 1.7\n", "\n", - "
\"The
" + "\"The" ] }, { @@ -347,7 +347,7 @@ "Because we are searching by Dataset ID, we don't need to specify any additional parameters to narrow down the data.\n", "\n", "### Fig 1.8\n", - "
\"The
\n" + "\"The\n" ] }, { @@ -357,7 +357,7 @@ "We now can access all the datasets specified in `obsId_list.txt`, as shown in Figure 1.9:\n", "\n", "### Fig 1.9\n", - "
\"The
\n", + "\"The\n", "\n", "We can select and download their data products as before." ] @@ -375,11 +375,11 @@ "\n", "Navigate to the MAST Portal at , and you will be greeted by a screen where the top looks like Figure 1.10. \n", "### Fig 1.10\n", - "
\"The
\n", + "\"The\n", "\n", "Click on \"Advanced Search\" (boxed in red in Figure 1.10). This will open up a new search tab, as shown in Figure 1.11:\n", "### Fig 1.11\n", - "
\"The
\n", + "\"The\n", "\n", "Fig 1.11 (above) shows the default search fields which appear. Depending on what you are looking for, these may or may not be the most helpful search fields. By unchecking some of the fields which we are not interested in searching by right now (Figure 1.12, boxed in green), and then entering the parameter values by which to narrow the search into each parameter's box, we generate Fig 1.12. One of the six fields (Mission) by which we are narrowing is boxed in a dashed blue line. The list of applied filters is boxed in red. A dashed pink box at the top left indicates that 2 records were found matching all of these parameters. To its left is an orange box around the \"Search\" button to press to bring up the list of results.\n", "\n", @@ -395,7 +395,7 @@ "|Product Type|spectrum|\n", "\n", "### Fig 1.12\n", - "
\"The
\n", + "\"The\n", "\n" ] }, @@ -443,7 +443,7 @@ "metadata": {}, "source": [ "### Fig 1.14\n", - "
\"The
\n", + "\"The\n", "\n", "Each dataset contains *many* files, most of which are calibration files or intermediate processing files. You may or may not want some of these intermediate files in addition to the final product file.\n", "In the leftmost \"Filters\" section of the Download Basket page, you can narrow which files will be downloaded (Fig 1.14, boxed in red).\n", From 6a1da4b697cb1110be8e23757ab8b2b32e91712e Mon Sep 17 00:00:00 2001 From: dulude Date: Mon, 11 Dec 2023 11:41:42 -0500 Subject: [PATCH 02/13] COS/Setup.ipynb: fixed three images. --- notebooks/COS/Setup/Setup.ipynb | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/notebooks/COS/Setup/Setup.ipynb b/notebooks/COS/Setup/Setup.ipynb index 74f724ff6..a4eddbb72 100644 --- a/notebooks/COS/Setup/Setup.ipynb +++ b/notebooks/COS/Setup/Setup.ipynb @@ -230,22 +230,15 @@ "First, we will check the CRDS website to determine what the current context is, as it changes regularly. In your browser, navigate to [the HST CRDS homepage](https://hst-crds.stsci.edu), and you will see a page as in Fig. 3.1:\n", "\n", "### Fig 3.1\n", - "\n", - "\n", - "![The CRDS homepage. There is a dropdown which lists all Hubble instruments. The table at the bottom of the page lists historical contexts.](figures/crds1.png \"CRDS Homepage\")\n", + "\"The\n", "\n", "At the bottom of this page is a list of recent contexts, titled \"Context History\". Clicking the context listed with the Status \"Operational\" (circled in red in Fig 3.1) will take you to that context's page, as shown in Fig. 3.2:\n", "\n", "### Fig 3.2\n", - "\n", - "\n", - "![The CRDS Historical References context page on the CRDS site. Each instrument is listed on the dropdown.\"> \n", - "By clicking the \"cos\" tab, (circled in red), you will be open up the tab, showing a page similar to Fig. 3.3, where you can find the current COS instrument context file: `hst_cos_.imap`. This filename is circled in red in Fig. 3.3.](./figures/crds2.png \"CRDS current 'Historical References' context page\")\n", + "\"The\n", "\n", "### Fig 3.3\n", - "\n", - "\n", - "![Showing the current COS context on the CRDS site. There is a large list of reference files, and the imap file labeled at the top of this list as hst_cos_0320.imap](figures/crds3.png \"Current COS context on the CRDS site\")\n", + "\"Showing\n", "\n", "Note down or copy the filename you just found." ] From ed90924a513525d1be1e558114c000f6842a4ea3 Mon Sep 17 00:00:00 2001 From: dulude Date: Mon, 11 Dec 2023 11:46:42 -0500 Subject: [PATCH 03/13] COS/LSF.ipynb: fixed two images. --- notebooks/COS/LSF/LSF.ipynb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/notebooks/COS/LSF/LSF.ipynb b/notebooks/COS/LSF/LSF.ipynb index 9e2854ab4..396fb98a0 100644 --- a/notebooks/COS/LSF/LSF.ipynb +++ b/notebooks/COS/LSF/LSF.ipynb @@ -298,15 +298,12 @@ "The COS team maintains up-to-date LSF files on the [COS Spectral Resolution page](https://www.stsci.edu/hst/instrumentation/cos/performance/spectral-resolution). Opening up this link leads to a page like that shown in Fig. 1.1, where the LSF files are discussed in detail. The bottom part of this page has links to all the relavent files. The links at the top of the page will take you to the relevant section. In Fig. 1.1, we have circled in black the link to the section pertaining to our data: FUV at the Lifetime Position: 3.\n", "\n", "###
Fig 1.1: Screenshot of the COS Spectral Resolution Site
\n", - "\n", - "![COS Spectral Resolution Site](figures/LSFHomepage.png \"COS Spectral Resolution Site\")\n", + "\"COS\n", "\n", "Clicking on the circled link takes us to the table of hyperlinks to all the files perataining to data taken with the FUV, Lifetime Postition 3 configutation, shown in Fig. 1.2:\n", "\n", "###
Fig 1.2: Screenshot of the COS Spectral Resolution Site - Focus on LP-POS 3
\n", - "\n", - "\n", - "![COS Spectral Resolution Site - Lifetime Position 3](figures/LSFHomepage2.png \"COS Spectral Resolution Site - Lifetime Position 3\")\n", + "\"COS\n", "\n", "Circled in solid red is the button to download the LSF file we need for our data with CENWAVE = 1291. Circled in dashed black is the corresponding CDSF.\n", "\n", From 36b11b29e3c6da5209e8455d63e64fa849eceac3 Mon Sep 17 00:00:00 2001 From: dulude Date: Mon, 11 Dec 2023 11:54:42 -0500 Subject: [PATCH 04/13] COS/DataDl.ipynb: fixed a bunch of images. --- notebooks/COS/DataDl/DataDl.ipynb | 57 ++++++++----------------------- 1 file changed, 14 insertions(+), 43 deletions(-) diff --git a/notebooks/COS/DataDl/DataDl.ipynb b/notebooks/COS/DataDl/DataDl.ipynb index 1afce398c..165c922c1 100644 --- a/notebooks/COS/DataDl/DataDl.ipynb +++ b/notebooks/COS/DataDl/DataDl.ipynb @@ -193,9 +193,7 @@ "source": [ "The search page of the HST-specific interface is laid out as in Figure 1.1:\n", "### Fig 1.1\n", - "\n", - "\n", - "![An image of the MAST search site. On the page there are boxes for each different criteria that you want in your search, such as Object Name in the top left, active instruments below that, and at the bottom of the page there is a box that you can fill with a certain column name and your desired criteria (if the criteria is not already on the page). At the top right is the 'My ST' button.](./figures/new_hst_search_login.png \"New HST-specific search website\")\n", + "\"An\n", "\n", "If you are accessing proprietary data, you will need to make an account or log in at the top right under \"MY ST\" (Fig 1.1, boxed in red). If you are accessing non-proprietary data, you may continue without logging in.\n" ] @@ -211,9 +209,7 @@ "* Are taken with the COS instrument, using the G160M grating and either the 1533 or the 1577 cenwave setting\n", "\n", "### Fig 1.2\n", - "\n", - "\n", - "![New HST-specific website search filled out with a COS data query, boxes with each criteria from above are highlighted with a red box. The central wavelength condition was added to the bottom box where you choose columns for criteria, since the central wavelength is not a pre-given criteria.](figures/hst_search_query_updated.png \"New HST-specific website search filled out with a COS data query\")" + "\"New" ] }, { @@ -223,9 +219,7 @@ "The above search results in the table shown in Figure 1.3. \n", "\n", "### Fig 1.3\n", - "\n", - "\n", - "![The page is now the search results page. At the top left are the 'Edit Search' box highlighted in dashed red. Below that is the 'Download Dataset' button highlighted with a green circle. Under that is the list of datasets, with each row beginning with a empty checkbox, followed by information about the dataset, such as search position, dataset name, target name, etc.](figures/new_hst_search_results.png \"Results from new HST-specific search website query\")\n", + "\"The\n", "\n", "If you need to change some parameters in your search - for instance, to also find data from the G130M grating - click on \"Edit Search\" (Fig 1.3, red dashed box).\n", "\n", @@ -240,9 +234,7 @@ "Most COS spectra have preview images (simple plots of flux by wavelength) which can be viewed before downloading the data. Clicking the dataset name (Fig 1.3, blue dashed oval) will take you to a page which shows the preview image, as well as some basic information about the data and whether there were any known failures during the operation. An example of such a page is shown in Figure 1.4.\n", "\n", "### Fig 1.4\n", - "\n", - "\n", - "![The page is now an image of a spectrum preview for dataset LPXK51020. It shows two plots of wavelength vs flux. Below is a list of exposure information, such as observation data, exposure time, release date, mode. At the very bottom of the page is the proposal ID along with the PI and CoIs.](figures/preview_spectrum_small.png \"Preview spectrum page\")" + "\"The" ] }, { @@ -252,15 +244,10 @@ "Returning to the results page shown in Fig 1.3 and clicking \"Download Data\" opens a window as shown in Figure 1.5. In this window you can search for filetypes using the search bar, and unselect/select all the data products shown in the filtered list (Fig 1.5, green circle). Clicking the \"Showing all filetypes\" box (Figure 1.5, red box) shows a drop-down (Figure 1.6) where you can choose to show/hide certain types of data such as the uncalibrated data. \n", "\n", "### Fig 1.5\n", - "\n", - "\n", - "![The image shows the a table of files in dataset LDJ1010. Each row shows different CalCOS products, such as the ASN file, X1DSUM, JIT, etc. The title of the table is the dataset name, and to the left of the name is the button to check all or none exposures, highlighted with a green circle. There are columns on the table that give information about the insturment used (COS) and the filter/grating (G140L). Above the table is a dropdown that allows you to choose the filetypes you wish to download.](figures/new_hst_search_downloading_all_files.png \"Choosing what to download in the new HST search website\")\n", + "\"The\n", "\n", "### Fig 1.6\n", - "\n", - "\n", - "![The image shows the same page as Figure 1.5, but the 'Showing all file types' dropdown button has been clicked. There are rows that have checkboxes on the left, each row from top to bottom is labled 'Calibrated', 'Uncalibrated', 'Aux/Other', 'Reference', 'Log/Jitter'](figures/new_hst_search_downloading_filetypes.png \"Choosing which data to download (calibrated/uncalibrated/etc.\")\n", + "\"The\n", "\n", "When all of your desired data products are checked, click \"Start Download\" (Fig 1.5, yellow dashed box). This will download a compressed \"zipped\" folder of all of your data, divided into subdirectories by the observation. Most operating systems can decompress these folders by default. For help decompressing the zipped files, you can follow these links for: [Windows](https://support.microsoft.com/en-us/windows/zip-and-unzip-files-8d28fa72-f2f9-712f-67df-f80cf89fd4e5) and [Mac](https://support.apple.com/guide/mac-help/zip-and-unzip-files-and-folders-on-mac-mchlp2528/mac). There are numerous ways to do this on Linux, however we have not vetted them." ] @@ -277,9 +264,7 @@ "\n", "### Fig 1.7\n", "\n", - "\n", - "![The image is showing the search page for MAST again. Halfway down the page is a box to input dataset name criteria. Above that is the obervation type box, which is composed of three check boxes. These boxes from left to right are 'All', 'Science', and 'Calibration'. The science box is the only one that is checked.](figures/new_hst_search_query2_small.png \"New HST-specific website search filled out with a specific dataset ID\")" + "\"The" ] }, { @@ -362,9 +347,7 @@ "Because we are searching by Dataset ID, we don't need to specify any additional parameters to narrow down the data.\n", "\n", "### Fig 1.8\n", - "\n", - "\n", - "![The image shows the MAST search page, with the top box filled in. The title of this box is 'Object name(s) and/or RA and Dec pair(s). The filled in box is the text file obsId_list.txt. The observations box below it has only the science box checked off.](figures/new_search_file_list_small.png \"File Upload Search Form\")\n" + "\"The" ] }, { @@ -374,9 +357,7 @@ "We now can access all the datasets specified in `obsId_list.txt`, as shown in Figure 1.9:\n", "\n", "### Fig 1.9\n", - "\n", - "\n", - "![The image shows the MAST search results page, with the three datasets from our text file shows in each row.](figures/new_search_file_list_res_small.png \"Upload List of Objects Search Results\")\n", + "\"The\n", "\n", "We can select and download their data products as before." ] @@ -394,15 +375,11 @@ "\n", "Navigate to the MAST Portal at , and you will be greeted by a screen where the top looks like Figure 1.10. \n", "### Fig 1.10\n", - "\n", - "\n", - "![The image shows the MAST portal, specifically the search box at the top.](figures/mastp_top.png \"Top of MAST Portal Home\")\n", + "\"The\n", "\n", "Click on \"Advanced Search\" (boxed in red in Figure 1.10). This will open up a new search tab, as shown in Figure 1.11:\n", "### Fig 1.11\n", - "\n", - "\n", - "![The image shows the advanced search pop-up. On the left of the pop-up is a list of check boxes for different search criteria, such as Target name, instrument, mission, etc. To the left of that are larger boxes for different critera, and inside these mobes are rows with checkboxes. For example, there is a larger box labeled 'Observation type' with two checkbox rows labeled 'science' and 'calibration'.](figures/mastp_adv.png \"The advanced search tab\")\n", + "\"The\n", "\n", "Fig 1.11 (above) shows the default search fields which appear. Depending on what you are looking for, these may or may not be the most helpful search fields. By unchecking some of the fields which we are not interested in searching by right now (Figure 1.12, boxed in green), and then entering the parameter values by which to narrow the search into each parameter's box, we generate Fig 1.12. One of the six fields (Mission) by which we are narrowing is boxed in a dashed blue line. The list of applied filters is boxed in red. A dashed pink box at the top left indicates that 2 records were found matching all of these parameters. To its left is an orange box around the \"Search\" button to press to bring up the list of results.\n", "\n", @@ -418,9 +395,7 @@ "|Product Type|spectrum|\n", "\n", "### Fig 1.12\n", - "\n", - "\n", - "![The image shows the same advanced search pop-up, filled out with our desired criteria. The criteria is highlighted, and above it is a list of the applied filters highlighted in red. The top of the pop-up has a 'Search' button, and also lists the records found. There are two records for our search.](figures/mastp_adv_2.png \"The advanced search tab with some selections\")\n", + "\"The\n", "\n" ] }, @@ -431,9 +406,7 @@ "Click the \"Search\" button (boxed in orange), and you will be brought to a page resembling Figure 1.13. \n", "\n", "### Fig 1.13\n", - "\n", - "\n", - "![The image shows the search results list, with consists of two rows for our search. To the left of the rows are checkboxes, then there is are images of a disk, spectra, and three dots. The rest of the columns of the rows show some criteria, such as the mission, observation type, etc. To the far right is the image of our object.](figures/mastp_res1.png \"Results of MAST Portal search\")" + "\"The" ] }, { @@ -470,9 +443,7 @@ "metadata": {}, "source": [ "### Fig 1.14\n", - "\n", - "\n", - "![The image shows the Download Manager. The left is a list of filters, where you can choose recommended products, product categories, extensions, and groups. To the left is a file list of all files for the observations. There are columns that label the file size, name, product type, etc.](figures/mastp_cart2.png \"MAST Portal Download Basket\")\n", + "\"The\n", "\n", "Each dataset contains *many* files, most of which are calibration files or intermediate processing files. You may or may not want some of these intermediate files in addition to the final product file.\n", "In the leftmost \"Filters\" section of the Download Basket page, you can narrow which files will be downloaded (Fig 1.14, boxed in red).\n", From bf54b2d7a394c76e99ef4c9033441217dfb6d151 Mon Sep 17 00:00:00 2001 From: Michael Dulude Date: Mon, 11 Dec 2023 12:01:43 -0500 Subject: [PATCH 05/13] Add WFC3 notebook 'wfc3_image_displayer_analyzer.ipynb' (#105) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * updated _toc.yml and _config.yml files * added trailing spaces to display_image.py, row_column_stats.py * updated notebook-level requirements.txt file. * wfc3_image_displayer_analyzer.ipynb: cleared notebook outputs. * Update display_image.py edits for PEP8 compliance and removing `ginga.util` dependence * Update row_column_stats.py changes for PEP8 compliance * Update row_column_stats.py last missing PEP8 changes * Update requirements.txt removing version pins and adding jupyter * Update wfc3_image_displayer_analyzer.ipynb changes for PEP8 compliance and some minor formatting * Update README.md changes for new information about creating a virtual environment * Update wfc3_image_displayer_analyzer.ipynb missed some PEP8 stuff; hopefully the last commit 🫠 --------- Co-authored-by: bjkuhn --- _config.yml | 1 - _toc.yml | 2 +- .../WFC3/image_displayer_analyzer/README.md | 33 +- .../image_displayer_analyzer/display_image.py | 311 ++++++++---------- .../image_displayer_analyzer/requirements.txt | 8 +- .../row_column_stats.py | 107 +++--- .../wfc3_image_displayer_analyzer.ipynb | 165 +++++----- 7 files changed, 305 insertions(+), 322 deletions(-) diff --git a/_config.yml b/_config.yml index 894344bab..3cf6d03b8 100644 --- a/_config.yml +++ b/_config.yml @@ -53,7 +53,6 @@ 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 f5cbbd213..89758b603 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, From d4e2c31a9efd8bdb0a5475ba21679bd75c66e4e8 Mon Sep 17 00:00:00 2001 From: dulude Date: Mon, 11 Dec 2023 12:02:08 -0500 Subject: [PATCH 06/13] STIS/calstis_2d_ccd.ipynb: fixed two images. --- notebooks/STIS/calstis/calstis_2d_ccd.ipynb | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/notebooks/STIS/calstis/calstis_2d_ccd.ipynb b/notebooks/STIS/calstis/calstis_2d_ccd.ipynb index bd9b3056b..c0d834deb 100644 --- a/notebooks/STIS/calstis/calstis_2d_ccd.ipynb +++ b/notebooks/STIS/calstis/calstis_2d_ccd.ipynb @@ -367,11 +367,8 @@ "The BLEVCORR step is part of basic 2-D image reduction for CCD data only. This step subtracts the electronic bias level for each line of the CCD image and trims the overscan regions off of the input image, leaving only the exposed portions of the image. \n", "\n", "Because the electronic bias level can vary with time and temperature, its value is determined from the overscan region in the particular exposure being processed. This bias is applied equally to real pixels (main detector and physical overscan) and the virtual overscan region (pixels that don't actually exist, but are recorded when the detector clocks out extra times after reading out all the parallel rows). A raw STIS CCD image in full frame unbinned mode has 19 leading and trailing columns of serial physical overscan in the AXIS1 (x direction), and 20 rows of virtual overscan in the AXIS2 (y direction); therefore the size of the uncalibrated and unbinned full framge CCD image is 1062(serial) $\\times$ 1044(parallel) pixels, with 1024 * 1024 exposed science pixels.\n", - "\n", "\n", - "![Graph illustrating parallel serial overscan corresponding to wavelength in the x-axis and virtual overscan corresponding to position along slit in the y-axis.](figures/CCD_overscan.jpg \"Graph illustrating parallel serial overscan corresponding to wavelength in the x-axis and virtual overscan corresponding to position along slit in the y-axis.\")" + "\"Graph" ] }, { @@ -382,11 +379,9 @@ "The electronic bias level is subtracted line-by-line. An initial value of electronic bias level is determined for each line of the image using the serial and parallel overscans, and a straight line is fitted to the bias as a function of image line. The intial electronic bias for each line is determined by taking the median of a predetermined subset of the trailing serial overscan pixels, which currently includes most trailing overscan region except the first and last three pixels, and pixels flagged with bad data quality flags. The actual overscan bias subtracted from the image is the value of the linear fit at a specific image line. The mean value of all overscan levels is written to the output SCI extension header as MEANBLEV.\n", "\n", "THE BLEVCORR step also trims the image of overscan. The size of the overscan regions depend on binning and whether the image if full frame or a subimage, and the locations of the overscan regions depend on which amplifier was used for readout. The number of pixels trimmed during CCD bias level correction on each side is given in the following table.\n", - "\n", "\n", - "![The number of pixels trimmed during CCD bias level correction on each side](figures/pixels_trimmed.jpg)\n" + "\"The\n", + "\n" ] }, { From 6c8512564c3bf9960d4906a32e8f08a90c8b953b Mon Sep 17 00:00:00 2001 From: dulude Date: Mon, 11 Dec 2023 12:07:35 -0500 Subject: [PATCH 07/13] WFC3/calwf3_with_v1.0_PCTE.ipynb: fixed three images. --- .../WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb b/notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb index 14d358b22..26ea2efa3 100644 --- a/notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb +++ b/notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb @@ -683,9 +683,7 @@ "source": [ "
Animated GIF of the v1.0 and v2.0 FLC image subsections:
\n", "\n", - "\n", - "\n", - "![An animated gif blinking between a subsection of background sky using the v1.0 and V2.0 pixel-based CTE corrections. The v2.0 background appears smoother with less noise and pixel variations.](example/v1_v2_bkg.gif \"An animated gif blinking between a subsection of background sky using the v1.0 and V2.0 pixel-based CTE corrections. The v2.0 background appears smoother with less noise and pixel variations.\")\n" + "\"An\n" ] }, { @@ -773,9 +771,7 @@ "metadata": {}, "source": [ "
Animated GIF of the v1.0 and v2.0 FLC image subsections:
\n", - "\n", - "\n", - "![An animated GIF of the v1.0 and v2.0 FLC image subsections](example/v1_v2_subsection.gif \"Animated GIF of the v1.0 and v2.0 FLC image subsections\")" + "\"An" ] }, { @@ -791,8 +787,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "\n", - "![Aperture photometry illustration](example/apphot_image.png \"Aperture photometry illustration\")" + "\"Aperture" ] }, { From 0471b325d072d1f7c8180145610a99643a10fa72 Mon Sep 17 00:00:00 2001 From: Michael Dulude Date: Mon, 11 Dec 2023 12:31:06 -0500 Subject: [PATCH 08/13] Add WFC3 notebook 'IR_IMA_Visualization_with_an_Example_of_Time_Variable_Background.ipynb' (#106) * updated _toc.yml and _config.yml files * ima_visualization_and_differencing.py: added trailing line * IR_IMA_Visualization_with_an_Example_of_Time_Variable_Background.ipynb: cleared all notebook outputs. * PEP8 corrections and removing unecessary imports, pinnin working code version in requirements.txt * a few more PEP8 corrections, removing Python version from requirement.txt * Recommended changes after notebook review. * Fix style error --------- Co-authored-by: annierose3 Co-authored-by: annierose3 <112646956+annierose3@users.noreply.github.com> Co-authored-by: Fred Dauphin <53876625+FDauphin@users.noreply.github.com> Co-authored-by: Hatice Karatay --- _config.yml | 1 + _toc.yml | 2 +- ..._Example_of_Time_Variable_Background.ipynb | 215 ++++++++++-------- .../ima_visualization_and_differencing.py | 206 +++++++++-------- .../ir_ima_visualization/requirements.txt | 2 +- 5 files changed, 228 insertions(+), 198 deletions(-) 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 From 8303468fe49cfa993f435b32a4a9b4a302a12fbe Mon Sep 17 00:00:00 2001 From: dulude Date: Mon, 11 Dec 2023 13:42:04 -0500 Subject: [PATCH 09/13] Setup.ipynb: Fixed "back to top of page" link --- notebooks/COS/Setup/Setup.ipynb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/notebooks/COS/Setup/Setup.ipynb b/notebooks/COS/Setup/Setup.ipynb index f03afc4c1..761b5be3c 100644 --- a/notebooks/COS/Setup/Setup.ipynb +++ b/notebooks/COS/Setup/Setup.ipynb @@ -411,9 +411,8 @@ "\n", "> *This tutorial was generated to be in compliance with the [STScI style guides](https://github.com/spacetelescope/style-guides) and would like to cite the [Jupyter guide](https://github.com/spacetelescope/style-guides/blob/master/templates/example_notebook.ipynb) in particular.*\n", "\n", - "[Top of Page](#topS)\n", - "\"Space \n", - "\n" + "Top of Page\n", + "\"Space " ] } ], @@ -433,7 +432,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.8.12" } }, "nbformat": 4, From 41567069d0d5ac85dad19b205fe1e7cdefb10f1c Mon Sep 17 00:00:00 2001 From: dulude Date: Tue, 12 Dec 2023 10:11:30 -0500 Subject: [PATCH 10/13] calwf3_with_v1.0_PCTE.ipynb: un-corrupted file. --- notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb b/notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb index 07cfc9d4d..26ea2efa3 100644 --- a/notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb +++ b/notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb @@ -772,6 +772,7 @@ "source": [ "
Animated GIF of the v1.0 and v2.0 FLC image subsections:
\n", "\"An" + ] }, { "cell_type": "markdown", @@ -988,7 +989,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.0" + "version": "3.8.12" }, "varInspector": { "cols": { From b871343aeb1d47d123bfc4f17439bc1c6759e4b4 Mon Sep 17 00:00:00 2001 From: dulude Date: Tue, 12 Dec 2023 10:35:33 -0500 Subject: [PATCH 11/13] calwf3_with_v1.0_PCTE.ipynb: fixed scaling of second and third images --- notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb b/notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb index 26ea2efa3..30d7f0033 100644 --- a/notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb +++ b/notebooks/WFC3/calwf3_v1.0_cte/calwf3_with_v1.0_PCTE.ipynb @@ -771,7 +771,8 @@ "metadata": {}, "source": [ "
Animated GIF of the v1.0 and v2.0 FLC image subsections:
\n", - "\"An" + "\n", + "\"An" ] }, { @@ -787,7 +788,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "\"Aperture" + "\"Aperture" ] }, { From 6e00489f8be6a0aaa844d083719164e3301dc0a2 Mon Sep 17 00:00:00 2001 From: srosagomez <113535721+srosagomez@users.noreply.github.com> Date: Thu, 14 Dec 2023 14:12:51 -0500 Subject: [PATCH 12/13] add HASP setup notebook and HASP folder (#152) * add HASP setup notebook * add requirements.txt and upgrade to python 3.11 * Add setup notebook to toc * Make changes to links/markdown in HASP/Setup.ipynb --------- Co-authored-by: Hatice Karatay --- _toc.yml | 3 + notebooks/HASP/Setup/Setup.ipynb | 407 ++++++++++++++++++++++++++ notebooks/HASP/Setup/requirements.txt | 2 + 3 files changed, 412 insertions(+) create mode 100644 notebooks/HASP/Setup/Setup.ipynb create mode 100644 notebooks/HASP/Setup/requirements.txt diff --git a/_toc.yml b/_toc.yml index cec17e3ab..7ff614603 100644 --- a/_toc.yml +++ b/_toc.yml @@ -42,6 +42,9 @@ parts: # - file: notebooks/DrizzlePac/sky_matching/sky_matching.ipynb - file: notebooks/DrizzlePac/use_ds9_regions_in_tweakreg/use_ds9_regions_in_tweakreg.ipynb - file: notebooks/DrizzlePac/using_updated_astrometry_solutions/using_updated_astrometry_solutions.ipynb + - caption: HSAP + chapters: + - file: notebooks/HSAP/Setup/Setup.ipynb - caption: NICMOS chapters: - file: notebooks/NICMOS/nicmos_unit_conversion/nicmos_unit_conversion.ipynb diff --git a/notebooks/HASP/Setup/Setup.ipynb b/notebooks/HASP/Setup/Setup.ipynb new file mode 100644 index 000000000..2fdd87c8d --- /dev/null +++ b/notebooks/HASP/Setup/Setup.ipynb @@ -0,0 +1,407 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "8346a078", + "metadata": {}, + "source": [ + "# Inputting User Data using the Hubble Advanced Spectral Products Script" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "1d2e317b", + "metadata": {}, + "source": [ + "### This Notebook is designed to walk you through downloading, installing, and using the **Hubble Advanced Spectral Products (HASP)** co-add script." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "01e97a32", + "metadata": {}, + "source": [ + "## Learning Goals: " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "ad4bc17b", + "metadata": {}, + "source": [ + "By the end of this tutorial, you will: \n", + "\n", + "* Download `conda` and create a `conda` environment\n", + "\n", + "* Download and install the co-add script\n", + "\n", + "* Learn how to run the script\n", + "\n", + "* Understand the naming conventions of the co-added output files\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "75d6e2e4", + "metadata": {}, + "source": [ + "## Table of Contents\n", + "**0. [Introduction](#introduction)**\n", + "\n", + "**1. [Downloading and Installing `conda`](#conda)**\n", + "\n", + "\\- 1.1 [Installing `conda`](#installconda)\n", + "\n", + "\\- 1.2 [Creating a `conda` Environment](#createenv)\n", + "\n", + "**2. [Downloading and Installing the HASP Script](#downloadcode)**\n", + "\n", + "**3. [Running the Co-add Script](#runscript)**\n", + "\n", + "\\- 3.1 [Running the Script](#runscript31)\n", + "\n", + "\\- 3.2 [Understanding the Output Files](#inspectoutput)\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "a73ce7ef", + "metadata": {}, + "source": [ + "\n", + "## 0. Introduction" + ] + }, + { + "cell_type": "markdown", + "id": "40af9618", + "metadata": {}, + "source": [ + "The Hubble Advanced Spectral Products (HASP) code is a script that co-adds spectra of the same target within programs. This software is able to co-add data taken with the spectrographs onboard the Hubble Space Telescope (HST); the Space Telescope Imaging Spectrograph (STIS) and the Cosmic Origins Spectrograph (COS). The Hubble Spectroscopic Legacy Archive (HSLA) uses this script to co-add these instruments’ data from the MAST archive to create high-quality spectra with a broad wavelength coverate (whenever possible from the ultraviolet to the near-infrared) that is publicly available for the scientific community. These custom co-addition notebooks will instruct users on how to produce their own co-adds in cases where the MAST archive data needs special processing or is rejected by the default filters used in the co-add script.\n", + "\n", + "The script first co-adds the observations for each grating for a given program, then it combines all gratings for the observation set. Finally, it co-adds the spectra of each observation set in the program to produce a fully co-added spectra for each target in a program. \n", + "\n", + "This notebook focuses primarily on the installation of the co-add code, and provides a quick overview on its usage. To see an example of downloading COS and STIS datasets, running the script, and analyzing the output, please check out our notebook CoaddTutorial.ipynb." + ] + }, + { + "cell_type": "markdown", + "id": "ecc750bf", + "metadata": {}, + "source": [ + "\n", + "## 1. Downloading and Installing `conda`" + ] + }, + { + "cell_type": "markdown", + "id": "47e1c12b", + "metadata": {}, + "source": [ + "\n", + "### 1.1 Installing `conda`\n", + "\n", + "Conda is a package, dependency, and environment manager that runs on Windows, Mac, and Linux. Conda allows us to easily install Python packages and create isolated conda environments, each with their own packages and dependencies. By switching between conda environments, we avoid conflicts between different versions of packages.\n", + "\n", + "We will create a conda environment to install the packages needed for the HASP script. We can first check if you have conda already installed by running the command in the terminal:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cdee82a9", + "metadata": {}, + "outputs": [], + "source": [ + "!conda --version" + ] + }, + { + "cell_type": "markdown", + "id": "63221b8d", + "metadata": {}, + "source": [ + "Running the command should print out the version of conda that you have installed (e.g. `conda 23.7.2`). If the command returns a statement saying that the package is unknown, then you do not have conda installed on your machine. You will need to download one of the conda distributions. \n", + "\n", + "There are a few different distributions of conda that you can install, depending on your preferences. [`Anaconda`](https://docs.anaconda.com/anaconda/install/index.html) is one distribution that carries a lot of pre-installed packages, some of which you won't use. [`Miniconda`](https://docs.conda.io/en/main/miniconda.html) is another distribution of conda that contains only the minimum packages. Finally, the [`Mamba`](https://mamba.readthedocs.io/en/latest/installation/mamba-installation.html) disctribution of conda is similar to `Miniconda`, but uses different parallelization and cache algorithms to increase speed and optimize memory.\n", + "\n", + "Once you have installed one of these clients, try running the above cell again to confirm that conda is installed." + ] + }, + { + "cell_type": "markdown", + "id": "49d07c7e", + "metadata": {}, + "source": [ + "\n", + "### 1.2 Creating a Conda Environment\n", + "\n", + "Once you've installed conda, we can create a conda environment. We will download all of the packages needed to run the HASP script in a new environment that we will create, called `hasp-env`. We will use this environment for all of the tutorial notebooks.\n", + "\n", + "The first step is to add the `conda-forge` channel to the list of avaible conda channels. Channels are where conda packages are stored and downloaded from, and `conda-forge` allows us to download additional packages for the code that the default conda channel may not have available. We can add this channel by running the following command in the terminal:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2b4274ee", + "metadata": {}, + "outputs": [], + "source": [ + "!conda config --add channels conda-forge" + ] + }, + { + "cell_type": "markdown", + "id": "7d741f45", + "metadata": {}, + "source": [ + "We can now create the conda environment, `hasp-env`. Note that this can take several minutes to run:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd8a8c1b", + "metadata": {}, + "outputs": [], + "source": [ + "!yes | conda create --name hasp-env python=3.11 notebook jupyterlab numpy astropy astroquery matplotlib" + ] + }, + { + "cell_type": "markdown", + "id": "db8a4820", + "metadata": {}, + "source": [ + "We also downloaded some additional packages that we will need outside of the HASP script to analyze the data. Once we activate the `conda` environment, as seen below, we can download the HASP script and run it. Note that you should run this in a terminal rather than in the cell below. Depending on your shell and operating system settings, you may need to restart your Jupyter notebook application in order for your environment to be fully activated in your notebook." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "be54962c", + "metadata": {}, + "outputs": [], + "source": [ + "!conda activate hasp-env" + ] + }, + { + "cell_type": "markdown", + "id": "3f1ec997", + "metadata": {}, + "source": [ + "Now that we created and activated a `conda` environment, we can now begin to download the HASP code." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "095e154d", + "metadata": {}, + "source": [ + "\n", + "## 2. Downloading and Installing the HASP Script" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "c3ced7eb", + "metadata": {}, + "source": [ + "We will download the HASP wrapper script from [the HASP Github repository](https://github.com/spacetelescope/hasp). Downloading this script will create a `hasp` directory, which will contain all of the required code. \n", + "\n", + "**You will only have to run **one** of the two options below, depending on your computer and Git settings.**\n", + "\n", + "#### Option A, using `pip`:\n", + "\n", + "`pip install` clones the reposoitory and install the packages according to the setup configuration of the repository. You may need to create a Personal Access Token (PAT) to use instead of your Github account's password, since support for password authentication was removed in 2021. You can learn how to create a PAT [here](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token).\n", + "\n", + "```\n", + "pip install git+https://github.com/spacetelescope/hasp.git\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "f4e25e36", + "metadata": {}, + "source": [ + "#### Option B, using `git clone`:\n", + "\n", + "While `git clone` still downloads the repository, it differs from `pip` in that it also downloads all of the history and files of the repository. If you have a password-protected SSH key, rather than a PAT, you can clone the repo by running the following code in your terminal. If you want to setup a SSH key, you can learn how to do so [here](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account).\n", + "\n", + "```\n", + "git clone git@github.com:spacetelescope/hasp.git\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "0615ee7f", + "metadata": {}, + "source": [ + "#### After you've downloaded the code using Options A or B, run the command below to download the script's dependencies:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c16e5246", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install ./hasp/." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "a0386593", + "metadata": {}, + "source": [ + "This will install additional dependencies using the `pyproject.toml` file. " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "01628f8c", + "metadata": {}, + "source": [ + "To run the wrapper, We only need to download the following COS and/or STIS files:\n", + "\n", + "* [X1D](https://hst-docs.stsci.edu/cosdhb/chapter-2-cos-data-files/2-4-cos-data-products#:~:text=in%20the%20association.-,One%2DDimensional%20Extracted%20Spectra%20(x1d%2C%20x1dsum),-The%20COS%20pipeline) - the one-dimensional extracted product spectra.\n", + " \n", + "* [SX1](https://hst-docs.stsci.edu/stisdhb/chapter-2-stis-data-structure/2-2-types-of-stis-files#:~:text=corrected%20imaging%20data.-,_sx1,-table) - the one-dimensional extracted spectra from combined or cosmic-ray rejected images. This file is only produced with STIS data. \n", + "\n", + "Make sure that all of these files, for every spectra you wish to abut, are in the same directory. The script will only co-add the files within this directory." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "9cd6cbc4", + "metadata": {}, + "source": [ + "\n", + "## 3. Running the Co-add Script\n", + "\n", + "\n", + "### 3.1 Running the Script\n", + "\n", + "Now that we have the wrapper installed, we can now run the co-add script.\n", + "\n", + "| Command-line Option | Value |\n", + "|----------|----------|\n", + "| `--input_directory` (`-i`) | The path to the directory that contains the data to be co-added (_required_)|\n", + "| `--output_directory` (`-o`) | The path to the directory that will contain the newly co-added products\\*\\* (_required_) |\n", + "| `--threshold` (`-t`) | The threshold for flux-based filtering (_optional_) |\n", + "| `--snrmax` (`-s`) | The maximum SNR for flux-based filtering (_optional_) |\n", + "| `--no_keyword_filtering` (`-k`) | Disable keyword based filtering (except for STIS PRISM data, which is always filtered) (_optional_) |\n", + "\n", + "\\*\\***Note:** If you wish to exclude certain data files from the co-add, you can just remove them from your input directory before you run the script.\n", + "\n", + "To finally run the script, open your terminal, activate your `conda` environment, and run:\n", + "\n", + "```\n", + "swrapper -i -o \n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "5a5dae88", + "metadata": {}, + "source": [ + "You should now have created the co-added spectra for your desired program." + ] + }, + { + "cell_type": "markdown", + "id": "7e368a5c", + "metadata": {}, + "source": [ + "\n", + "### 3.2 Understanding the Output Files\n", + "\n", + "The script produces multiple different files with abutted spectra. Currently, the script outputs abutted products for a single program. It first creates co-added spectra for each grating of a single observation set:\n", + "\n", + "`hst_programID_instrument_targetname_grating_obset_cspec.fits`\n", + "\n", + "It then co-adds the spectra of all gratings for a single observation set:\n", + "\n", + "`hst_programID_instrument_targetname_allGratings_obset_cspec.fits`\n", + "\n", + "Finally, it co-adds all abutted observation sets' spectra to create a final co-added product for a single target:\n", + "\n", + "`hst_programID_instrument_targetname_allGratings_cspec.fits`\n", + "\n", + "An example of this will be below. These filenames are the output files for a STIS GD71 dataset that is co-added in the CoaddTutorial.ipynb notebook example. Here, the `programID` is `7656`, the `instrument` is `STIS`, and the `targetname` is `gd71`.\n", + "\n", + "| Step | Filename | Description |\n", + "|----------|----------|----------|\n", + "| 1 | `hst_7656_stis_gd71_g140l_o4a520_cspec.fits` | Co-adding all `G140L` observations for the observation set, `O4A520`. |\n", + "| 2 | `hst_7656_stis_gd71_g140l-g230l-g430l-g750l_o4a520_cspec.fits` | Co-adding all observations taken at every grating for the observation set, `O4A520`. |\n", + "| 3 | `hst_7656_stis_gd71_g140l-g230l-g430l-g750l_o4a5_cspec.fits` | Co-adding all GD71 observations at each grating for this program, `O4A5`. |\n", + "\n", + "***Note: HST file naming conventions use a combination of three letters and/or numbers to have a unique association between a PI's proposal ID and program ID, meaning that `o4a5` at the end of `hst_7656_stis_gd71_g140l-g230l-g430l-g750l_o4a5_cspec.fits` is essentially the program ID for our example. Check out more information on the [MAST HST file naming convention page](https://archive.stsci.edu/hlsp/ipppssoot.html)*** \n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "551c86c8", + "metadata": {}, + "source": [ + "## About this Notebook\n", + "**Author:** Sierra Gomez (sigomez@stsci.edu)\n", + "\n", + "**Updated on:** 12/04/2023\n", + "\n", + "*This tutorial was generated to be in compliance with the [STScI style guides](https://github.com/spacetelescope/style-guides) and would like to cite the [Jupyter guide](https://github.com/spacetelescope/style-guides/blob/master/templates/example_notebook.ipynb) in particular.*\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "164f5842", + "metadata": {}, + "source": [ + "\"Space" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/HASP/Setup/requirements.txt b/notebooks/HASP/Setup/requirements.txt new file mode 100644 index 000000000..c5eb502c2 --- /dev/null +++ b/notebooks/HASP/Setup/requirements.txt @@ -0,0 +1,2 @@ +jupyterlab>=4.0.9 +notebook>=7.0.6 \ No newline at end of file From c0c754e1aad1f4a32cf6e2468e2f793aec3448a2 Mon Sep 17 00:00:00 2001 From: Michael Dulude Date: Thu, 14 Dec 2023 15:11:53 -0500 Subject: [PATCH 13/13] Update _toc.yml Fixed typo in path to HASP notebook 'setup.ipynb' in _toc.yml --- _toc.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_toc.yml b/_toc.yml index 7ff614603..3285a7751 100644 --- a/_toc.yml +++ b/_toc.yml @@ -42,9 +42,9 @@ parts: # - file: notebooks/DrizzlePac/sky_matching/sky_matching.ipynb - file: notebooks/DrizzlePac/use_ds9_regions_in_tweakreg/use_ds9_regions_in_tweakreg.ipynb - file: notebooks/DrizzlePac/using_updated_astrometry_solutions/using_updated_astrometry_solutions.ipynb - - caption: HSAP + - caption: HASP chapters: - - file: notebooks/HSAP/Setup/Setup.ipynb + - file: notebooks/HASP/Setup/Setup.ipynb - caption: NICMOS chapters: - file: notebooks/NICMOS/nicmos_unit_conversion/nicmos_unit_conversion.ipynb