diff --git a/_toc.yml b/_toc.yml
index f5cbbd213..3285a7751 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: HASP
+ chapters:
+ - file: notebooks/HASP/Setup/Setup.ipynb
- caption: NICMOS
chapters:
- file: notebooks/NICMOS/nicmos_unit_conversion/nicmos_unit_conversion.ipynb
@@ -65,8 +68,8 @@ 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/ir_ima_visualization/IR_IMA_Visualization_with_an_Example_of_Time_Variable_Background.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
- file: notebooks/WFC3/persistence/wfc3_ir_persistence.ipynb
diff --git a/notebooks/COS/DataDl/DataDl.ipynb b/notebooks/COS/DataDl/DataDl.ipynb
index 7dd57ae41..7370a4b9a 100644
--- a/notebooks/COS/DataDl/DataDl.ipynb
+++ b/notebooks/COS/DataDl/DataDl.ipynb
@@ -195,7 +195,7 @@
"### Fig 1.1\n",
"\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"
+ "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"
]
},
{
@@ -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",
- "
"
+ ""
]
},
{
@@ -219,7 +219,7 @@
"The above search results in the table shown in Figure 1.3. \n",
"\n",
"### Fig 1.3\n",
- " \n",
+ "\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",
- " "
+ ""
]
},
{
@@ -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",
- " \n",
+ "\n",
"\n",
"### Fig 1.6\n",
- " \n",
+ "\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",
- " "
+ ""
]
},
{
@@ -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",
- " \n"
+ "\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",
- " \n",
+ "\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",
- " \n",
+ "\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",
"\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",
- " \n",
+ "\n",
"\n"
]
},
@@ -406,7 +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",
- " "
+ ""
]
},
{
@@ -443,7 +443,7 @@
"metadata": {},
"source": [
"### Fig 1.14\n",
- " \n",
+ "\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",
diff --git a/notebooks/COS/LSF/LSF.ipynb b/notebooks/COS/LSF/LSF.ipynb
index 556def5fe..0f1800963 100644
--- a/notebooks/COS/LSF/LSF.ipynb
+++ b/notebooks/COS/LSF/LSF.ipynb
@@ -298,12 +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",
+ "\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",
"\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",
diff --git a/notebooks/COS/Setup/Setup.ipynb b/notebooks/COS/Setup/Setup.ipynb
index 92e327992..761b5be3c 100644
--- a/notebooks/COS/Setup/Setup.ipynb
+++ b/notebooks/COS/Setup/Setup.ipynb
@@ -230,17 +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",
"\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",
- "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.\n",
+ "\n",
"\n",
"### Fig 3.3\n",
- " \n",
+ "\n",
"\n",
"Note down or copy the filename you just found."
]
@@ -413,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",
- " \n",
- "\n"
+ "Top of Page\n",
+ " "
]
}
],
@@ -435,7 +432,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.10.9"
+ "version": "3.8.12"
}
},
"nbformat": 4,
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": [
+ ""
+ ]
+ }
+ ],
+ "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
diff --git a/notebooks/STIS/calstis/calstis_2d_ccd.ipynb b/notebooks/STIS/calstis/calstis_2d_ccd.ipynb
index 7c0083294..c0d834deb 100644
--- a/notebooks/STIS/calstis/calstis_2d_ccd.ipynb
+++ b/notebooks/STIS/calstis/calstis_2d_ccd.ipynb
@@ -368,9 +368,7 @@
"\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",
- " \n",
- ""
+ ""
]
},
{
@@ -382,9 +380,8 @@
"\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",
- " \n",
- ""
+ "\n",
+ "\n"
]
},
{
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 efc08eb9e..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",
- ""
+ "\n",
+ ""
]
},
{
@@ -787,7 +788,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- ""
+ ""
]
},
{
@@ -989,7 +990,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.0"
+ "version": "3.8.12"
},
"varInspector": {
"cols": {
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",
" "
]
- },
- {
- "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,
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",
- "\n",
+ "\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",
- ""
+ ""
]
},
{
@@ -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