PlasmaPy logo

XRTpy Documentation

This is the documentation for XRTpy: a Python package being developed for the analysis of observations made by the X-Ray Telescope (XRT) [Golub et al., 2007] on the Hinode spacecraft [Kosugi et al., 2007].

Installing XRTpy

Installing Python

XRTpy requires Python 3.9 or newer. If you do not have Python installed already, here are the instructions to download Python and install it.

Tip

New versions of Python are released annually in October, and it can take a few months for the scientific Python ecosystem to catch up. If you have trouble installing xrtpy on the most recent Python version between October and ∼March, then try installing it on the second most recent version.

Installing XRTpy with pip

To install the most recent release of xrtpy on PyPI with pip into an existing Python 3.9+ environment on macOS or Linux, open a terminal and run:

python -m pip install xrtpy

On some systems, it might be necessary to specify the Python version number by using python3, python3.9, python3.10, or python3.11 instead of python.

To install XRTpy on Windows, run:

py -3.10 -m pip install xrtpy

The version of Python may be changed from 3.10 to another supported Python 3.9+ release that has been installed on your computer.

For more detailed information, please refer to this tutorial on installing packages.

Installing XRTpy with Conda

Conda is a package management system and environment manager that is commonly used in the scientific Python ecosystem. Conda lets us create and switch between Python environments that are isolated from each other and the system installation. Conda can also be used for packages written in languages other than Python.

After installing Conda or miniconda, xrtpy can be installed into an activated Conda environment by opening a terminal and running:

conda install -c conda-forge xrtpy

Here -c conda-forge indicates that xrtpy should be installed from the conda-forge channel.

To install xrtpy into another existing Conda environment, append -n env_name to the previous command, where env_name is replaced with the name of the environment.

To create a new environment with xrtpy installed in it, run:

conda create -n env_name -c conda-forge xrtpy

where env_name is replaced by the name of the environment. To activate this environment, run:

conda activate env_name

To update xrtpy to the most recent version within a currently activated Conda environment, run:

conda update xrtpy

Tip

Creating a Conda environment can sometimes take a few minutes. If it takes longer than that, try updating to the newest version of Conda with conda update conda or checking out these tips for improving Conda performance.

Installing XRTpy with Anaconda Navigator

Note

This section contains instructions on how to install XRTpy with Anaconda Navigator at the time of writing. For the most up-to-date information, please go to the official documentation on installing Anaconda Navigator and managing packages.

Anaconda Navigator is a graphical user interface (GUI) for Conda that can be used to install Python packages. It is installed automatically with newer versions of Conda. If you are using Miniconda or a different Conda environment, you can install it with conda install anaconda-navigator. After that it can be opened by entering anaconda-navigator in the terminal.

First, go to the Environments tab and select Channels. If conda-forge is not listed, then go to Add, enter https://conda.anaconda.org/conda-forge, and click on Update channels and then Update index.

Next, while on the Environments tab, select the environment that you would like to install xrtpy in. The default is generally base (root). Optionally, you may select Create to start a new environment. In the search bar, enter xrtpy. Click on the checkbox next to xrtpy, and select Apply to begin the installation process.

To test the installation, click on the icon that should be present next to the activated environment, and select Open terminal. Enter python in the terminal, and then import xrtpy to make sure it works.

Installing XRTpy from source code

Obtaining official releases

A ZIP file containing the source code for official releases of xrtpy can be obtained from PyPI or from Zenodo.

Alternatively, official releases can be downloaded from the releases page on XRTpy’s GitHub repository.

Obtaining source code from GitHub

If you have git installed on your computer, you may clone XRTpy’s GitHub repository and access the source code from the most recent development version by running:

git clone https://github.com/xrtpy/xrtpy.git

The repository will be cloned inside a new subdirectory called xrtpy.

If you do not have git installed on your computer, then you may download the most recent source code from XRTpy’s GitHub repository by going to Code and selecting Download ZIP. Unzipping the file will create a subdirectory called XRTpy that contains the source code.

Building and installing

To install the downloaded version of xrtpy, enter the xrtpy directory and run:

pip install .

If you expect to occasionally edit the source code, instead run:

pip install -e .[developer]

The -e flag makes the installation editable and [developer] indicates that all of the dependencies needed for developing XRTpy will be installed.

Note

If you noticed any places where the installation instructions could be improved or have become out of date, please create an issue on XRTpy’s GitHub repository. It would really help!

Hinode Satellite

About the X-Ray Telescope (XRT)

Hinode

Hinode is a joint mission involving the space agencies of Japan, the United States, Europe, and the United Kingdom. It is depicted in the illustration shown above. The spacecraft is equipped with three instruments: the Solar Optical Telescope (SOT), the Extreme Ultraviolet Imaging Spectrometer (EIS), and the X-Ray Telescope (XRT). These instruments are designed to provide multi-wavelength data from the photosphere to the upper corona. The solar spacecraft spacecraft was launched at 6:36 a.m on September 23, 2006 (Japan Standard Time) and placed into a polar, sun-synchronous orbit, enabling continuous observations of the Sun. For further information, visit NASA’s Hinode space mission to the Sun.

The X-Ray Telescope

The X-Ray Telescope (XRT) is an instrument onboard the Hinode spacecraft. With its remarkable capabilities, the XRT provides high-resolution images of the solar corona’s hottest material, ranging from 1,000,000 to 10,000,000 Kelvin. Visit the official xrt-cfa-harvard website for mission overview information about the XRT.

Tip

Visit the XRT Picture of the Week and the Hinode-XRT YouTube page for captivating visual content showcasing the XRT’s solar observations.

SolarSoft XRT Analysis Guide

The SolarSoft XRT Analysis Guide is a comprehensive resource for analysis of XRT data. It includes both an Instrument Guide and an overview of the X-Ray telescope’s hardware components. The XRT software was originally created in Interactive Data Language (IDL). IDL is a software programming language used to analyze and create meaningful information from numerical data.

Note

Please note that the SolarSoft XRT Analysis Guide does not serve as a guide for using XRTpy. It focuses solely on the analysis of XRT data using the IDL software.

Getting Started

XRTpy is a Python package being developed for the analysis of observations made by the X-Ray Telescope (XRT) on the board Hinode spacecraft. This page is intended for new users of xrtpy. For more background information about XRT please refer to the SolarSoft XRT Analysis Guide.

XRTpy Objects:

XRTpy currently offers Channel, Effective Area, and Temperature Response classes. We have also introduced new functionality, including the ablility to derive temperatures and emission measures for a pair of images, sharpen images using the point spread function, and a function to correct synoptic images for the light leak (visible stray light) that XRT has developed. Visit our Example page for detail notebook example guides on how to use the XRTpy classes and functions.

Channel

Channel is an instrument configuration class that contains the properties of particular XRT filters. It provides a detailed information on the filter channel, including the Charge-Coupled Device (CCD), Entrance Filter, Focus-Filter(s), Geometry, and Mirror(s).

Effective Area

XRTpy calculates the effective areas for a set of XRT filter channels paired with thicknesses of the CCD contamination layer. For more information about the instrumental spectral responses, refer to the SolarSoft XRT Analysis Guide.

Temperature Response

XRTpy calculates the temperature response for each XRT filter channel, assuming a spectral emission model, refer to Narukage et al. [2011] and Narukage et al. [2014]. The XRT default emission model is CHIANTI atomic database version 10.0 with coronal abundances Feldman [2014]. This structure contains data and information about a plasma emission model, as a function of wavelength and temperature.

Deriving Temperature and Emission Measure for a Pair of Images

XRTpy provides a routine, temperature_from_filter_ratio, that employs the objects listed above to derive the temperature and emission measure in for a given pair of images using the filter ratio method. This uses the same methods as in the SolarSoft IDL routine of the same name. Familiarize yourself with the utilization of this function through the notebook example provided on our Example page.

Enhancing Images Sharpness with Point Spread Function - Deconvolution

Deconvolution is a powerful technique used to enhance image sharpness by mitigating the blurring effect caused by the telescope’s point spread function (PSF). It is particularly useful for removing the blurring around sharp objects or features in the XRT image. To learn how to use deconvolve, refer to the notebook examples provided on our Example page.

Subtracting Light Leak from XRT Synoptic Composite Images

We have developed a specialized function designed to subtract light leak, remove_lightleak, which refers to visible stray light, from XRT synoptic composite images. By applying this function, you can effectively remove the unwanted artifacts caused by light leak, resulting in cleaner and more accurate images for further analysis and interpretation. Explore our Example page for a notebook example that demonstrate the usage of this function.

Abundance Model

The standard XRT temperature response routines are calculated assuming CHIANTI coronal abundances, Feldman [2014]. Additionally, XRTpy offers the ability to choose two other sets of CHIANTI abundances i.e. Hybrid and Photospheric. The Hybrid abundances are base on Fludra and Schmelz [1999] and Photospheric abundances are base on Grevesse et al. [2007]. The CHIANTI files contain data and information about a plasma emission model, as a function of wavelength and temperature. Visit XRT temperature response with other choice of abundances for future detailed information.

Note

XRTpy has future plans to accept other plasma emission spectra models.

XRTpy defaults to using CHIANTI “coronal” abundance. You can specify the other abundances by defining the abundance type name, such as “hybrid” or “photospheric” in the abundance_model parameter. For example:

xrtpy.response.TemperatureResponseFundamental(
    'Al-poly',
    '2022/07/04T23:43:12',
    abundance_model = 'Hybrid'
    )

The abundance_model parameter is used in the same format in temperature_from_filter_ratio.

Data Products

The XRT website provides readily available XRT data products, including both Level 1 and Level 2 data. The Level 1 Data section contains an extensive archive of all Level 1 XRT data that has been calibrated using the xrt_prep routine, with units expressed in instrumental Data Numbers. Additionally, for users interested in synoptic images, Level 2 Synoptics data is available, which consists of composite images from the twice-daily synoptic program. These images have been processed and are available in the archive. For more detailed information about our XRT data products, please visit the XRT data products site, where you can find comprehensive data resources and references.

X-Ray Filter Channel

The XRT controls filter imaging using two sequentially positioned filter wheels. Refer to Section 3 in the X-Ray Telescope Instrument Guide in the SolarSoft XRT Analysis Guide for more information about the XRT filters. The existing filters are structured as so:

  1. Filter Configuration
    1. Filter position
      1. Filter Wheel 1:
        • Open

        • Aluminum Polyimide (Al-poly)

        • Carbon Polyimide (C-poly)

        • Beryllium Thin (Be-thin)

        • Beryllium Medium (Be-med)

        • Aluminum Medium (Al-med)

      2. Filter Wheel 2:
        • Open

        • Aluminum Mesh (Al-mesh)

        • Titanium Polyimide (Ti-poly)

        • G-band

        • Aluminum Thick (Al-thick)

        • Beryllium Thick (Be-thick)

    2. Open

      Each filter wheel has an empty position, named ‘Open’. The open position is in place when a filter on the other filter wheel is being used.

    3. G-band

      The G-Band filter allows visible light into the telescope and onto the CCD. XRTpy does not calculate the effective area or the temperature response for the G-Band filter.

Note

Filters are expressed by their abbreviation when used in XRTpy. For example, if we want to explore the filter channel that selects the titanium-on-polyimide filter, then the string would be 'Ti-poly'. The process is the same for all XRT filter channels.

Examples

In this section, we provide a catalog of example Jupyter notebooks that demonstrate the various functionalities offered by XRTpy. These notebooks serve as practical guides for utilizing the features and capabilities of XRTpy in different scenarios. By exploring these examples, users can gain a better understanding of how to effectively use XRTpy for their analysis tasks.

Getting started

Channel Properties - Exploring XRT Instrument Configuration

We will explore the X-Ray Telescope (XRT) instrument properties using XRTpy’s Channel object. The Channel object provides convenient methods and attributes to access and analyze various aspects of the XRT instrument configuration.

[1]:
# Import the xrtpy package
import xrtpy

Begin by defining a filter channel by its common abbreviation. In this example we will be exploring the titanium-on-polyimide filter. For detailed information about various filter channels and their characteristics, you can refer to the xrtpy- X-Ray Filter Channel section.

[2]:
# Define the filter channel abbreviation
Filter = "Ti-poly"

To further explore the properties and characteristics of the defined filter channel, we will create a Channel object using xrtpy.response.Channel. By inserting the Filter variable as an input to the xrtpy.response.Channel object, we can conveniently work with the properties associated with the titanium-on-polyimide filter.

[3]:
channel = xrtpy.response.Channel(Filter)

Now that we have created our channel object, we can delve into the X-Ray Telescope (XRT) instrument and its properties. We will start by examining basic information about the XRT instrument.

[4]:
# Display relevant information about the selected filter, observatory, and instrument
print("Selected filter:", channel.name)
print("\nObservatory:", channel.observatory)
print("Instrument:", channel.instrument)
Selected filter: Ti-poly

Observatory: Hinode
Instrument: XRT
Note: Instrument Properties

It is important to note that most instrument properties of the X-Ray Telescope (XRT) remain the same regardless of the specific filter being used. This means that many characteristics and specifications of the XRT instrument, such as its dimensions, field of view, and detector properties, are independent of the selected filter.

Contents
  1. Charge-Coupled Device

  2. Entrance Filter

  3. Focus-Filter

  4. Geometry

  5. Mirror 1 and 2

  6. Instrument Plotting

Charge-Coupled-Device (CCD)

The channel.ccd object reviews properties associated with the Charge-Coupled-Device (CCD) camera of the X-Ray Telescope (XRT) instrument.

We can explore various characteristics of the CCD camera, such as its quantum_efficiency and pixel size to list a few.

[5]:
print(channel.ccd.ccd_name)

print("\nPixel size: ", channel.ccd.ccd_pixel_size)

print("Full well: ", channel.ccd.ccd_full_well)
print("Gain left: ", channel.ccd.ccd_gain_left)
print("Gain right: ", channel.ccd.ccd_gain_right)
print("eV pre electron: ", channel.ccd.ccd_energy_per_electron)
Hinode/XRT Flight Model CCD

Pixel size:  13.5 micron
Full well:  222000.0 electron
Gain left:  58.79999923706055 electron / DN
Gain right:  57.5 electron / DN
eV pre electron:  3.6500000953674316 eV / electron
Entrance Filter

We can explore the XRT entrance filter properties utilizing channel.entrancefilter object.

[6]:
print(channel.entrancefilter.entrancefilter_name)
print("Material: ", channel.entrancefilter.entrancefilter_material)
print("Thickness: ", channel.entrancefilter.entrancefilter_thickness)
print("Density: ", channel.entrancefilter.entrancefilter_density)
Entrance filters
Material:  ['Al2O3' 'Al' 'Al2O3' 'polyimide']
Thickness:  [  75. 1492.    0. 2030.] Angstrom
Density:  [3.97  2.699 3.97  1.43 ] g / cm3
Focus-Filter

The XRT data is recorded through nine X-ray filters, which are implemented using two filter wheels. By utilizing the channel.filter_# notation, where # represents filter wheel 1 or 2, we can explore detailed information about the selected XRT channel filter.

We are exploring the titanium-on-polyimide filter located in filter wheel 2, we will be utilizing the channel.filter_2 object. This enables us to gather specific information about the properties and characteristics of this particular filter.

It’s worth noting that exploring the other filter will yield the result “Open,” as it’s not use. For more comprehensive information about the XRT filters, you can refer to the X-Ray Filter Channel documentation.

[7]:
print("Filter Wheel:", channel.filter_2.filter_name)
print("\nFilter material:", channel.filter_2.filter_material)
print("Thickness: ", channel.filter_2.filter_thickness)
print("Density: ", channel.filter_2.filter_density)
Filter Wheel: Ti filter on polyimide

Filter material: ['TiO2' 'Ti' 'TiO2' 'polyimide']
Thickness:  [  75. 2338.    0. 2522.] Angstrom
Density:  [4.26 4.54 4.26 1.43] g / cm3
Geometry

We can explore geometry factors in the XRT using channel.geometry.

[8]:
print(channel.geometry.geometry_name)
print("\nFocal length:", channel.geometry.geometry_focal_len)
print("Aperture Area:", channel.geometry.geometry_aperture_area)
Hinode/XRT Flight Model geometry

Focal length: 270.753 cm
Aperture Area: 2.28 cm2
Mirror

The XRT is equipped with two mirrors, each having a unique configuration. We can access the properties of these mirrors using the channel_mirror_# notation, where # represents the first or second mirror surface. In this example, we will explore several XRT properties related to mirror 1 using the channel_mirror_1 object.

[9]:
print(channel.mirror_1.mirror_name)
print("Material: ", channel.mirror_1.mirror_material)
print("Density: ", channel.mirror_1.mirror_density)
print("Graze_angle: ", channel.mirror_1.mirror_graze_angle)
Hinode/XRT Flight Model mirror
Material:  Zerodur
Density:  2.5299999713897705 g / cm3
Graze_angle:  0.9100000262260437 deg
Instrument Plotting
Plotting XRT properties - Transmittance

Define the XRT transmission in channel by referencing transmission.

[10]:
transmission = channel.transmission

Define the XRT wavelength in channel by referencing wavelength.

[11]:
wavelength = channel.wavelength

Create a plotting function that plots the transmission versus wavelength.

[12]:
def plot_transmission():
    import matplotlib.pyplot as plt

    plt.figure(figsize=(10, 6))

    plt.plot(wavelength, transmission, label=f"{channel.name}")

    plt.title("X-Ray Telescope", fontsize=15)
    plt.xlabel(r"$\lambda$ [Å]", fontsize=15)
    plt.ylabel(r"Transmittance", fontsize=15)
    plt.legend(fontsize=20)
    plt.xlim(-5, 80)
    plt.xticks(fontsize=15)
    plt.yticks(fontsize=15)

    plt.grid(color="lightgrey")
    plt.show()

Run plot_transmission function to create the plot.

[13]:
plot_transmission()
_images/notebooks_getting_started_channel_35_0.png

Using Astropy Units

In scientific computing, we often represent physical quantities as numbers.

[2]:
distance_in_miles = 50
time_in_hours = 2
velocity_in_mph = distance_in_miles / time_in_hours
print(velocity_in_mph)
25.0

Representing a physical quantity as a number has risks. We might unknowingly perform operations with different units, like time_in_seconds + time_in_hours. We might even accidentally perform operations with physically incompatible units, like length + time, without catching our mistake. We can avoid these problems by using a units package.

This notebook introduces astropy.units with an emphasis on the functionality needed to work with xrtpy. We typically import this subpackage as u.

[3]:
import astropy.units as u
Contents
  1. Unit basics

  2. Unit operations

  3. Unit conversations

  4. Detaching units and values

  5. Equivalencies

  6. Physical constants

  7. Optimizing unit operations

  8. Physical Types

Unit basics

We can create a physical quantity by multiplying or dividing a number or array with a unit.

[4]:
distance = 60 * u.km
print(distance)
60.0 km

This operation creates a Quantity: a number, sequence, or array that has been assigned a physical unit.

[5]:
type(distance)
[5]:
astropy.units.quantity.Quantity

We can also create an object by using the Quantity class itself.

[6]:
time = u.Quantity(120, u.min)

We can create Quantity objects with compound units.

[7]:
88 * u.imperial.mile / u.hour
[7]:
$88 \; \mathrm{\frac{mi}{h}}$

We can even create Quantity objects that are explicitly dimensionless.

[8]:
3 * u.dimensionless_unscaled
[8]:
$3 \; \mathrm{}$

We can also create a Quantity based off of a NumPy array or a list.

[9]:
import numpy as np

np.array([2.5, 3.2, 1.1]) * u.kg
[9]:
$[2.5,~3.2,~1.1] \; \mathrm{kg}$
[10]:
[2, 3, 4] * u.m / u.s
[10]:
$[2,~3,~4] \; \mathrm{\frac{m}{s}}$
Unit operations

Operations between Quantity objects handle unit conversions automatically. We can add Quantity objects together as long as their units have the same physical type.

[11]:
1 * u.m + 25 * u.cm
[11]:
$1.25 \; \mathrm{m}$

Units get handled automatically during operations like multiplication, division, and exponentiation.

[12]:
velocity = distance / time
print(velocity)
0.5 km / min
[13]:
area = distance**2
print(area)
3600.0 km2

Attempting an operation between physically incompatible units gives us an error, which we can use to find bugs in our code.

[14]:
3 * u.m + 3 * u.s
UnitConversionError: 's' (time) and 'm' (length) are not convertible


During handling of the above exception, another exception occurred:

UnitConversionError: Can only apply 'add' function to quantities with compatible dimensions

Quantity objects behave very similarly to NumPy arrays because Quantity is a subclass of numpy.ndarray.

[15]:
balmer_series = [656.279, 486.135, 434.0472, 410.1734] * u.nm
 = balmer_series[0]
print()
656.279 nm
[16]:
np.max(balmer_series)
[16]:
$656.279 \; \mathrm{nm}$

Most frequently encountered NumPy and SciPy functions can be used with Quantity objects. However, Quantity objects lose their units with some operations.

Unit conversions

The to method allows us to convert a Quantity to different units of the same physical type. This method accepts strings that represent a unit (including compound units) or a unit object.

[17]:
velocity.to("m/s")
[17]:
$8.3333333 \; \mathrm{\frac{m}{s}}$
[18]:
velocity.to(u.m / u.s)
[18]:
$8.3333333 \; \mathrm{\frac{m}{s}}$

The si and cgs attributes convert the Quantity to SI or CGS units, respectively.

[19]:
velocity.si
[19]:
$8.3333333 \; \mathrm{\frac{m}{s}}$
[20]:
velocity.cgs
[20]:
$833.33333 \; \mathrm{\frac{cm}{s}}$
Detaching units and values

The value attribute of a Quantity provides the number (as a NumPy scalar) or NumPy array without the unit.

[21]:
time.value
[21]:
120.0

The unit attribute of a Quantity provides the unit without the value.

[22]:
time.unit
[22]:
$\mathrm{min}$
Equivalencies

Occasionally the electron-volt (eV) as a unit of temperature. This is a shortcut for describing the thermal energy per particle, or more accurately the temperature multiplied by the Boltzmann constant, \(k_B\). Because an electron-volt is a unit of energy rather than temperature, we cannot directly convert electron-volts to kelvin.

[23]:
u.eV.to("K")
UnitConversionError: 'eV' (energy/torque/work) and 'K' (temperature) are not convertible

To handle non-standard unit conversions, astropy.units allows the use of equivalencies. The conversion from eV to K can be done by using the temperature_energy() equivalency.

[24]:
(1 * u.eV).to("K", equivalencies=u.temperature_energy())
[24]:
$11604.518 \; \mathrm{K}$

Radians are treated dimensionlessly when the dimensionless_angles() equivalency is in effect. Note that this equivalency does not account for the multiplicative factor of \(2π\) that is used when converting between frequency and angular frequency.

[25]:
(3.2 * u.rad / u.s).to("1 / s", equivalencies=u.dimensionless_angles())
[25]:
$3.2 \; \mathrm{\frac{1}{s}}$
Physical constants

We can use astropy.constants to access the most commonly needed physical constants.

[26]:
from astropy.constants import c, e, k_B

print(c)
  Name   = Speed of light in vacuum
  Value  = 299792458.0
  Uncertainty  = 0.0
  Unit  = m / s
  Reference = CODATA 2018

A Constant behaves very similarly to a Quantity. For example, we can use the Boltzmann constant to mimic the behavior of u.temperature_energy().

[27]:
thermal_energy_per_particle = 0.6 * u.keV
temperature = thermal_energy_per_particle / k_B
print(temperature.to("MK"))
6.962710872930049 MK

Electromagnetic constants often need the unit system to be specified. Code within PlasmaPy uses SI units.

[28]:
2 * e
TypeError: Constant 'e' does not have physically compatible units across all systems of units and cannot be combined with other values without specifying a system (eg. e.emu)

[29]:
2 * e.si
[29]:
$3.2043533 \times 10^{-19} \; \mathrm{C}$
Optimizing unit operations

Astropy’s documentation includes performance tips for using astropy.units in computationally intensive situations. For example, putting compound units in parentheses reduces the need to make multiple copies of the data.

[30]:
volume = 0.62 * (u.barn * u.Mpc)
Physical types

A physical type corresponds to physical quantities with dimensionally compatible units. Astropy has functionality that represents different physical types. These physical type objects can be accessed using either the physical_type attribute of a unit or get_physical_type().

[31]:
(u.m**2 / u.s).physical_type
[31]:
PhysicalType({'diffusivity', 'kinematic viscosity'})
[32]:
u.get_physical_type("number density")
[32]:
PhysicalType('number density')

These physical type objects can be used for dimensional analysis.

[33]:
energy_density = (u.J * u.m**-3).physical_type
velocity = u.get_physical_type("velocity")
print(energy_density * velocity)
energy flux/irradiance

Computing response functions

Effective Area Analysis for X-Ray Telescope (XRT)

In this example, we will explore the effective areas for different XRT filter channels, considering their respective thicknesses of the CCD contamination layer at a specific date and time. Understanding the effective areas is essential for accurately interpreting and quantifying X-ray signals. Let’s dive into the details and calculations below.

[1]:
# Import the xrtpy module for X-ray Telescope (XRT) calculations
import xrtpy
Contents
  1. Define Filter

  2. Define Date & Time

  3. Effective-Area-Fundamental

  4. Effective Area Function

  5. Plotting the Effective Area versus Wavelength

Define a Filter Channel

In XRT analysis, the filter channels play a crucial role in determining the effective areas. A filter channel refers to a specific configuration of filter materials. By defining the filter channel appropriately, we can accurately calculate the effective area for a given XRT configuration.

Let’s begin by defining a filter channel using its abbreviation. For example, if we want to explore the effective area for an aluminum-on-polyimide filter channel, we need to specify the relevant abbreviation. This step ensures that we consider the correct filter configuration in our calculations. Refer to the xrtpy- X-Ray Filter Channel section for more information.

[2]:
# Define the filter channel abbreviation
Filter = "Al-poly"
Define a date and time

Let’s consider exploring the data captured approximately a year after the launch date. We need to define a specific date and time. We will use the format “YYYY-MM-DD HH:MM:SS” to represent the desired date and time. The date and time can be specified using various formats depending on your preference and data availability. Please refer to the sunpy-time documentation for detailed examples and further information on different date and time string formats.

[3]:
# Define the date and time for analysis
date_time = "2007-09-22T22:59:59"
EffectiveAreaFundamental

The EffectiveAreaFundamental object plays a central role in calculating the effective area. It provides a range of functions and properties that are essential for this computation. By utilizing the EffectiveAreaFundamental object, we can accurately determine the effective area based on the specified filter channel, date, and time.

To access the functionality of the EffectiveAreaFundamental object, we need to reference it by inserting the defined Filter and date_time.

[4]:
# Create an instance of the EffectiveAreaFundamental object
Effective_Area_Fundamental = xrtpy.response.EffectiveAreaFundamental(Filter, date_time)
Effective Area function

To actually calculate the effective area function we call the effective_area() method of the Effective_Area_Fundamental object.

[5]:
# Calculate the effective area
effective_area = Effective_Area_Fundamental.effective_area()

The effective_area function returns the effective area for a selected filter, date, and time as an astropy-quantity with astropy.units.

[6]:
print("Effective Area:\n", effective_area)
Effective Area:
 [2.78457457e-10 7.94914547e-10 2.06647656e-09 ... 2.07749128e-15
 0.00000000e+00 0.00000000e+00] cm2
Plotting the Effective Area versus Wavelength

To gain insights into the X-ray Telescope (XRT) observations, we will plot the effective area against the corresponding wavelengths. This visualization allows us to understand how the effective area varies across different wavelengths and provides valuable information for interpreting XRT data.

We will utilize the channel_wavelength property within the Effective_Area_Fundamental object to get the wavelengths.

[7]:
# Wavelength unit in Angstroms A˚
wavelength = Effective_Area_Fundamental.channel_wavelength

To further analyze the effective area data, we will focus on the observations relative to the spacecraft launch date. This will allow us to identify any differences or trends in the effective area during the early stages of the mission. We will define the effective area data for the launch date in the same manner as previously shown.

[8]:
# Create an instance of the EffectiveAreaFundamental object for the launch date and time of the same filter channel
relative_launch_date_time = "2006-09-22T22:59:59"

EAF_launch_date_time = xrtpy.response.EffectiveAreaFundamental(
    Filter, relative_launch_date_time
)
[9]:
# launch date effective area
launch_date_effective_area = EAF_launch_date_time.effective_area()

Create a plotting function that plots the effective area versus wavelegth.

[10]:
def plot_effective_area():
    import matplotlib.pyplot as plt

    plt.figure(figsize=(30, 13))

    plt.plot(
        wavelength,
        effective_area,
        linewidth=8,
        label=f"{Filter} {date_time}",
    )

    plt.plot(
        wavelength,
        launch_date_effective_area,
        linewidth=8,
        label=f"{Filter} {relative_launch_date_time}",
    )

    plt.title("XRT Effective Area\nAl-Poly", fontsize=30)
    plt.xlabel("Wavelength (Å)", fontsize=30)
    plt.ylabel("Effective Area ($cm^{2}$)", fontsize=30)
    plt.legend(fontsize=30)

    plt.xticks(fontsize=27)
    plt.yticks(fontsize=27)
    plt.xlim(0, 60)

    plt.grid(color="lightgrey")
    plt.show()

Run plot_effective_area function to create the plot.

[11]:
plot_effective_area()
_images/notebooks_computing_functions_effective_area_28_0.png

By plotting the effective area at the spacecraft launch date and comparing it to the effective area a year after, we can observe and analyze any differences. These differences arise from variations in the contamination layer thickness on the CCD which blocks some of the X-rays thus reducing the effective area. For detailed information about the calculation of the XRT CCD contaminant layer thickness, you can refer to the Montana State University Solar Physics site.

To further understand the factors contributing to the observed differences, additional information can be found in the research paper by Narukage et. al. (2011). This paper provides valuable insights into the characteristics and behavior of the XRT instrument, which can aid in interpreting the effective area data.

Temperature Response Analysis for X-Ray Telescope (XRT)

This notebook explores the temperature response of X-ray channels in the X-Ray Telescope (XRT). The temperature response provides valuable insights into how the XRT instrument detects and responds to different temperatures of X-ray emissions. By assuming a specific spectral emission model at a given date, we can investigate the behavior of the XRT channels.

To begin the analysis, we will import the necessary packages that enable us to perform the temperature response calculations and generate visualizations.

[1]:
import matplotlib.pyplot as plt
import numpy as np

import xrtpy

Let’s dive in and explore the fascinating temperature response characteristics of the XRT!

Contents
  1. Define a Filter Channel

  2. Define Date & Time

  3. Temperature-Response-Fundamental

  4. Temperature Response Function

  5. Plot Temperature Response

Define a Filter Channel

A filter channel is defined by its common abbreviation, which represents a specific type of filter used to modify the X-ray radiation passing through. In this example, we will explore the carbon-on-polyimide filter (abbreviated as “C-poly”).

For detailed information about various filter channels and their characteristics, you can refer to the xrtpy- X-Ray Filter Channel section.

[2]:
filter_ = "C-poly"
Define a date and time

In order to analyze the temperature response, it is necessary to specify a date and time for the analysis. The date and time can be defined together using specific string formats. To explore the data captured a year after the launch date, we will define the date and time accordingly.

For detailed examples and further information about date and time string formats, you can refer to the sunpy-time documentation.

[3]:
date_time = "2007-09-22T21:59:59"
TemperatureResponseFundamental

The TemperatureResponseFundamental object is a crucial component that provides all the necessary functions and properties for calculating the temperature response in our analysis. By referencing this object, we can access the required methods and attributes for further calculations.

To create a TemperatureResponseFundamental object, you need to provide the defined filter channel (Filter) and the desired date and time (date_time). Additionally, you can specify the abundance model of interest, such as Photospheric, which influences the temperature response calculations.

[4]:
Temperature_Response_Fundamental = xrtpy.response.TemperatureResponseFundamental(
    filter_, date_time, abundance_model="Photospheric"
)
Temperature Response function

To calculate the temperature response, simply call the temperature_response() function on the Temperature_Response_Fundamental object. This function utilizes the specified filter, date, and abundance model to generate the temperature response as a result.

[5]:
temperature_response = Temperature_Response_Fundamental.temperature_response()

The temperature_response() function returns the temperature response for the selected filter, date, and time. The returned value is an astropy-quantity object with associated astropy.units.

[6]:
print("Temperature Response:\n", temperature_response)
Temperature Response:
 [1.75050807e-32 2.70263514e-32 4.36848081e-32 7.64222509e-32
 1.44553318e-31 2.90457420e-31 6.10688786e-31 1.31813616e-30
 2.85199117e-30 6.04093244e-30 1.20584729e-29 2.25580103e-29
 4.06436412e-29 7.15874537e-29 1.23900438e-28 2.11433884e-28
 3.53237680e-28 5.72715150e-28 8.97569641e-28 1.35530879e-27
 1.96217565e-27 2.72120713e-27 3.65282015e-27 4.77711444e-27
 6.06054054e-27 7.50321445e-27 9.36405909e-27 1.20323078e-26
 1.55414815e-26 1.96738272e-26 2.43687806e-26 2.96895640e-26
 3.56257848e-26 4.20174413e-26 4.86211023e-26 5.51967813e-26
 6.14517852e-26 6.69301462e-26 7.09635243e-26 7.27766017e-26
 7.16208307e-26 6.70431811e-26 5.93449932e-26 5.04143353e-26
 4.26660561e-26 3.71134670e-26 3.34334665e-26 3.09955692e-26
 2.93387374e-26 2.81622487e-26 2.72785171e-26 2.65705658e-26
 2.59631790e-26 2.54128549e-26 2.48900542e-26 2.43838341e-26
 2.38875772e-26 2.34020863e-26 2.29292986e-26 2.24705072e-26
 2.20243354e-26] cm5 DN / (pix s)
Plotting the Temperature-Response

In this section, we will visualize the temperature response by plotting the temperature_response function against the corresponding temperatures. It’s important to note that the CHIANTI temperatures used in this plot are the temperatures of the solar plasma and are independent of the channel filter.

The CHIANTI temperatures are stored in the Temperature_Response_Fundamental object and are provided in units of Kelvin (K). These temperatures serve as the independent variable for plotting the temperature response.

By visualizing the temperature response, we can gain insights into how it varies with respect to temperature, providing a deeper understanding of the XRT channelcharacteristics.

Additionally, if you wish to explore more details about the CHIANTI database, you can find further information at chiantidatrbase.org.

[7]:
CHIANTI_temperature = Temperature_Response_Fundamental.CHIANTI_temperature

We take the log of the CHIANTI_temperature for plotting, which compresses the scale and enhances the visibility of the variations for lower temperatures.

[8]:
log_CHIANTI_temperature = np.log10(CHIANTI_temperature.value)

In addition, we will compare the data shortly after the spacecraft launch date with the current data. This allows us to identify any differences or variations in the temperature response over time.

We define a new temperature response data for the launch date. The process for obtaining this data is the same as previously shown, where we specify the filter, launch date, and abundance model.

By comparing the temperature response at the launch date with the current temperature response, we can gain insights into any changes that may have occurred over time. This comparison helps us understand the stability and evolution of the XRT.

[9]:
launch_date_time = "2006-09-22T23:59:59"
[10]:
launch_date_temperature_response = xrtpy.response.TemperatureResponseFundamental(
    filter_, launch_date_time, abundance_model="Photospheric"
).temperature_response()

Create a plotting function that plots the temperature_response versus log_CHIANTI_temperature for the chosen filter, date, and time.

[11]:
def plotting_temperature_response():
    plt.figure(figsize=(30, 12))

    plt.plot(
        log_CHIANTI_temperature,
        np.log10(temperature_response.value),
        linewidth=4,
        label=f"{filter_} {date_time}",
    )
    plt.plot(
        log_CHIANTI_temperature,
        np.log10(launch_date_temperature_response.value),
        linewidth=3,
        label=f"{filter_} {launch_date_time}",
        color="red",
    )

    plt.title("XRT Temperature Response", fontsize=30)
    plt.xlabel("Log(T) ($K$)", fontsize=27)
    plt.ylabel("$DN$ $cm^5$ $ s^-1$ $pix^-1$", fontsize=27)
    plt.legend(fontsize=30)

    plt.xticks(fontsize=25)
    plt.yticks(fontsize=25)

    plt.grid()
    plt.show()

Run plotting_temperature_response function to create the plot.

[12]:
plotting_temperature_response()
_images/notebooks_computing_functions_temperature_response_31_0.png

Plotting the temperature response at launch date and a year after highlights the differences. This is due to the contamination layer thickness on the CCD. Information about the XRT CCD contaminant layer thickness calculation can be found at Montana State University Solar Physics site. In addition, more information can be found referencing Narukage et. al. (2011).

Data analysis

Using deconvolve to deconvolve images

deconvolve can sharpen images using the point spread function derived for Hinode XRT

Deconvolution is ordinarily used when wanting to remove the blurring around sharp objects or features caused by the telescope’s point spread function. Here we show an example of its use for an XRT image taken during the transit of Venus in 2012. We download this data from the VSO using methods in SunPy.

[1]:
from sunpy.map import Map
from sunpy.net import Fido
from sunpy.net import attrs as a

from xrtpy.image_correction.deconvolve import deconvolve

result = Fido.search(
    a.Time("2012-06-05 21:58:39", "2012-06-05 21:59:00"), a.Instrument("xrt")
)

data_file = Fido.fetch(result[0], progress=False)
/home/docs/checkouts/readthedocs.org/user_builds/xrtpy/envs/latest/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm

deconvolve takes a SunPy map as input and returns the deconvolved image and metadata as a SunPy map.

[2]:
in_map = Map(data_file)
out_map = deconvolve(in_map)
Files Downloaded:   0%|          | 0/1 [00:00<?, ?file/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:   0%|          | 0.00/33.6M [00:00<?, ?B/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:   0%|          | 33.0k/33.6M [00:00<01:44, 322kB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:   4%|▍         | 1.34M/33.6M [00:00<00:04, 7.75MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  12%|█▏        | 3.87M/33.6M [00:00<00:01, 15.7MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  21%|██        | 6.91M/33.6M [00:00<00:01, 21.4MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  27%|██▋       | 9.06M/33.6M [00:00<00:01, 17.8MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  33%|███▎      | 11.0M/33.6M [00:00<00:01, 17.9MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  39%|███▉      | 13.0M/33.6M [00:00<00:01, 18.8MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  47%|████▋     | 15.8M/33.6M [00:00<00:00, 21.4MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  54%|█████▍    | 18.1M/33.6M [00:00<00:00, 21.7MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  60%|██████    | 20.3M/33.6M [00:01<00:00, 20.2MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  67%|██████▋   | 22.4M/33.6M [00:01<00:00, 19.9MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  76%|███████▌  | 25.4M/33.6M [00:01<00:00, 22.4MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  82%|████████▏ | 27.7M/33.6M [00:01<00:00, 21.0MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  89%|████████▊ | 29.8M/33.6M [00:01<00:00, 14.6MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  94%|█████████▍| 31.5M/33.6M [00:01<00:00, 12.4MB/s]
xrtpy.XRT20170324_151721.0.PSF560.fits:  98%|█████████▊| 33.0M/33.6M [00:02<00:00, 12.4MB/s]
Files Downloaded: 100%|██████████| 1/1 [00:02<00:00,  2.13s/file]
Files Downloaded:   0%|          | 0/1 [00:00<?, ?file/s]
xrtpy.XRT20170324_161721.0.PSF1000.fits:   0%|          | 0.00/33.6M [00:00<?, ?B/s]
xrtpy.XRT20170324_161721.0.PSF1000.fits:   2%|▏         | 795k/33.6M [00:00<00:04, 7.91MB/s]Exception ignored in: <function BaseEventLoop.__del__ at 0x7f6666a1e840>
Traceback (most recent call last):
  File "/home/docs/.asdf/installs/python/3.11.6/lib/python3.11/asyncio/base_events.py", line 694, in __del__
    self.close()
  File "/home/docs/.asdf/installs/python/3.11.6/lib/python3.11/asyncio/unix_events.py", line 71, in close
    self.remove_signal_handler(sig)
  File "/home/docs/.asdf/installs/python/3.11.6/lib/python3.11/asyncio/unix_events.py", line 160, in remove_signal_handler
    signal.signal(sig, handler)
  File "/home/docs/.asdf/installs/python/3.11.6/lib/python3.11/signal.py", line 56, in signal
    handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: signal only works in main thread of the main interpreter
Exception ignored in: <function BaseEventLoop.__del__ at 0x7f6666a1e840>
Traceback (most recent call last):
  File "/home/docs/.asdf/installs/python/3.11.6/lib/python3.11/asyncio/base_events.py", line 694, in __del__
    self.close()
  File "/home/docs/.asdf/installs/python/3.11.6/lib/python3.11/asyncio/unix_events.py", line 71, in close
    self.remove_signal_handler(sig)
  File "/home/docs/.asdf/installs/python/3.11.6/lib/python3.11/asyncio/unix_events.py", line 160, in remove_signal_handler
    signal.signal(sig, handler)
  File "/home/docs/.asdf/installs/python/3.11.6/lib/python3.11/signal.py", line 56, in signal
    handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: signal only works in main thread of the main interpreter

xrtpy.XRT20170324_161721.0.PSF1000.fits:  16%|█▌        | 5.25M/33.6M [00:00<00:00, 29.2MB/s]
xrtpy.XRT20170324_161721.0.PSF1000.fits:  24%|██▍       | 8.17M/33.6M [00:00<00:01, 23.4MB/s]
xrtpy.XRT20170324_161721.0.PSF1000.fits:  32%|███▏      | 10.6M/33.6M [00:00<00:01, 20.8MB/s]
xrtpy.XRT20170324_161721.0.PSF1000.fits:  41%|████      | 13.8M/33.6M [00:00<00:00, 24.0MB/s]
xrtpy.XRT20170324_161721.0.PSF1000.fits:  52%|█████▏    | 17.3M/33.6M [00:00<00:00, 27.6MB/s]
xrtpy.XRT20170324_161721.0.PSF1000.fits:  61%|██████    | 20.5M/33.6M [00:00<00:00, 28.7MB/s]
xrtpy.XRT20170324_161721.0.PSF1000.fits:  71%|███████▏  | 23.9M/33.6M [00:00<00:00, 30.5MB/s]
xrtpy.XRT20170324_161721.0.PSF1000.fits:  82%|████████▏ | 27.5M/33.6M [00:00<00:00, 31.9MB/s]
xrtpy.XRT20170324_161721.0.PSF1000.fits:  92%|█████████▏| 30.9M/33.6M [00:01<00:00, 32.5MB/s]
Files Downloaded: 100%|██████████| 1/1 [00:01<00:00,  1.29s/file]

deconvolve uses the Richardson-Lucy deconvolution algorithm and takes a few optional input parameters including niter (no. of iterations to perform, 5 by default), pdf1keV (to use the point spread function defined at 1.0 keV rather than the default one defined at 560 eV) and verbose (False by default). Above we just used the default settings.

To see the effects of the deconvolution we plot both the input and output images:

[3]:
import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1, projection=in_map)
in_map.plot(axes=ax1, title="Original Image")
ax2 = fig.add_subplot(1, 2, 2, projection=out_map)
out_map.plot(axes=ax2, title="Deconvolved Image")
fig.subplots_adjust(wspace=0.5)
plt.show()
_images/notebooks_data_analysis_Deconvolving_XRT_images_7_0.png

Using the remove_lightleak function to analyze XRT composite images

The remove_lightleak function is built to subtract light leak (visible stray light) image from XRT synoptic composite images. Level two synoptic composite image data is available at xrt.cfa.harvard.edu. This template will guide you through the method of using remove_lightleak.

Begin by importing remove_lightleak function from XRTpy.

[1]:
from pathlib import Path
[2]:
import pkg_resources
import sunpy.map

from xrtpy.image_correction.remove_lightleak import remove_lightleak
/tmp/ipykernel_1534/490298938.py:1: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
  import pkg_resources
/home/docs/checkouts/readthedocs.org/user_builds/xrtpy/envs/latest/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm

This example will be using XRT synoptic data from the first day of summer of 2015.

[3]:
directory = pkg_resources.resource_filename(
    "xrtpy", "image_correction/data/example_data"
)
data_file = Path(directory) / "comp_XRT20150621_055911.7.fits"

print("File used:\n", data_file.name)
File used:
 comp_XRT20150621_055911.7.fits

Take on `sunpy.map.Map <https://docs.sunpy.org/en/stable/code_ref/map.html>`__ to run the composite data file.

[4]:
in_map = sunpy.map.Map(data_file)

The remove_lightleak function takes a `sunpy.map.Map <https://docs.sunpy.org/en/stable/code_ref/map.html>`__ as input and returns the composite image and metadata as a Map.

[5]:
out_map = remove_lightleak(in_map)
Files Downloaded:   0%|          | 0/1 [00:00<?, ?file/s]
xrtpy.term_p2am_20150718_160913.fits:   0%|          | 0.00/4.21M [00:00<?, ?B/s]
xrtpy.term_p2am_20150718_160913.fits:  10%|▉         | 419k/4.21M [00:00<00:00, 4.19MB/s]
xrtpy.term_p2am_20150718_160913.fits:  74%|███████▎  | 3.10M/4.21M [00:00<00:00, 17.5MB/s]
Files Downloaded: 100%|██████████| 1/1 [00:00<00:00,  3.14file/s]
[6]:
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm

fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1, projection=in_map)
in_map.plot(axes=ax1, title="Original Image", norm=LogNorm(1.0, None))
ax2 = fig.add_subplot(1, 2, 2, projection=out_map)
out_map.plot(axes=ax2, title="Light Leak Subtracted Image", norm=LogNorm(1.0, None))
fig.subplots_adjust(wspace=0.5)
plt.show()
_images/notebooks_data_analysis_Remove_lightleak_11_0.png

Deriving temperatures using composite images and the filter ratio method

The temperature_from_filter_ratio routine in XTRpy derives the temperature and emission measure in XRT images by using two images taken at nearly the same time but using different filters. When doing this you can use standard XRT Level 1 data files or you can use “composite” images. Composite images are created from two or three images taken sequentially with the same pointing and filter but with different exposure times. Generally one wants to use either a long and short pair of exposures or a long-medium-short triple of exposures. Such composite images are made routinely for the synoptic archive of Hinode. The idea behind composite images is that pixels in the image that are saturated in the long exposure are replaced by pixels from the short (or medium) exposure that are not saturated and thus create an image with a greater dynamic range than you would get with a single image.

We start by importing temperature_from_filter_ratio.

To use composite images, we need to generate their exposure maps, which are images where each pixel value is the exposure time of the image from which the pixel came. Most of the pixels will generally be from the long exposure image, but for the brightest part of the image, the pixels will come from the medium or short exposure image that was used to generate the composite image. The composite images that we’ll use can be downloaded from the XRT archive.

For this example, we will use the download_file utility from astropy to download the composite files. We also use the routine filename2repo_path from XRTpy to find the correct URL for each file to be downloaded.

[1]:
from astropy.utils.data import download_file

from xrtpy.response.temperature_from_filter_ratio import temperature_from_filter_ratio
from xrtpy.util.filename2repo_path import filename2repo_path

filename1 = "comp_XRT20210730_175810.1.fits"
filename2 = "comp_XRT20210730_175831.6.fits"
url1 = filename2repo_path(filename1, join=True)
url2 = filename2repo_path(filename2, join=True)
# These files will go under your astropy cache directory, typically ~/.astropy/cache/download/url/
file1 = download_file(url1)
file2 = download_file(url2)
/home/docs/checkouts/readthedocs.org/user_builds/xrtpy/envs/latest/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm

Then we need to calculate the exposure maps, which will be used with temperature_from_filter_ratio.

[2]:
from xrtpy.util.make_exposure_map import make_exposure_map

expmap1 = make_exposure_map(file1)
expmap2 = make_exposure_map(file2)

Note that each call to this routine will result in more files being downloaded. Now we are ready to call temperature_from_filter_ratio. This routine takes Sunpy maps as input (not related to exposure maps).

[3]:
from sunpy.map import Map

map1 = Map(file1)
map2 = Map(file2)
T_EM = temperature_from_filter_ratio(map1, map2, expmap1=expmap1, expmap2=expmap2)

temperature_from_filter_ratio returns a named tuple of maps: Tmap, EMmap, Terrmap, EMerrmap. To make a nice looking plot, we use matplotlib.

[4]:
import matplotlib.pyplot as plt

fig = plt.figure()
T_e = T_EM.Tmap
m = Map(10.0**T_e.data, T_e.meta)
m.plot(vmin=8.0e5, vmax=3.0e6, cmap="turbo")
m.draw_limb()
m.draw_grid()
cb = plt.colorbar()
plt.show()
_images/notebooks_data_analysis_Temperature_using_composites_11_0.png

Using temperature_from_filter_ratio to analyze XRT data

This example demonstrates how to use temperature_from_filter_ratio to calculate the temperature and emission measure in an image using the filter ratio method.

First we need to import temperature_from_filter_ratio.

As an example we will use the test data included in XRTpy, though data with the right characteristics in the XRT archive could also be used. It’s necessary to use two images that are the same size and different filters. To get good results the images should have been taken close in time as well, ideally adjacent in time. Note that not all filter ratios produce good results.

This data was generated using the IDL routine xrt_prep.pro from SolarSoft and is unnormalized. Data in the Level 1 archive are normalized, which is also okay to use, though the IDL routine xrt_teem.pro did not allow that. For normalized data the image data is multiplied by the exposure time before analysis.

[1]:
import sunpy.map
from sunpy.net import Fido
from sunpy.net import attrs as a

from xrtpy.response.temperature_from_filter_ratio import temperature_from_filter_ratio
/home/docs/checkouts/readthedocs.org/user_builds/xrtpy/envs/latest/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm
[2]:
result = Fido.search(
    a.Time("2011-01-28 01:31:55", "2011-01-28 01:32:05"), a.Instrument("xrt")
)

data_files = Fido.fetch(result, progress=False)
[3]:
file1 = data_files[1]
file2 = data_files[0]
print("Files used:\n", file1, "\n", file2)
Files used:
 /home/docs/sunpy/data/l1_xrt20110128_013204_9.fits
 /home/docs/sunpy/data/l1_xrt20110128_013155_9.fits

temperature_from_filter_ratio uses Sunpy maps as input.

[4]:
map1 = sunpy.map.Map(file1)
map2 = sunpy.map.Map(file2)
[5]:
print(
    map1.fits_header["TELESCOP"],
    map1.fits_header["INSTRUME"],
)
print(
    "\n File 1 used:\n",
    file1,
    "\n Observation date:",
    map1.fits_header["DATE_OBS"],
    map1.fits_header["TIMESYS"],
    "\n Filter Wheel 1:",
    map1.fits_header["EC_FW1_"],
    map1.fits_header["EC_FW1"],
    "\n Filter Wheel 2:",
    map1.fits_header["EC_FW2_"],
    map1.fits_header["EC_FW2"],
    "\n Dimension:",
    map1.fits_header["NAXIS1"],
    map1.fits_header["NAXIS1"],
)

print(
    "\nFile 2 used:\n",
    file2,
    "\n Observation date:",
    map2.fits_header["DATE_OBS"],
    map2.fits_header["TIMESYS"],
    "\n Filter Wheel 1:",
    map2.fits_header["EC_FW1_"],
    map2.fits_header["EC_FW1"],
    "\n Filter Wheel 2:",
    map2.fits_header["EC_FW2_"],
    map2.fits_header["EC_FW2"],
    "\n Dimension:",
    map2.fits_header["NAXIS1"],
    map2.fits_header["NAXIS1"],
)
HINODE XRT

 File 1 used:
 /home/docs/sunpy/data/l1_xrt20110128_013204_9.fits
 Observation date: 2011-01-28T01:32:04.998 UTC (TBR)
 Filter Wheel 1: Be_thin 3
 Filter Wheel 2: Open 0
 Dimension: 384 384

File 2 used:
 /home/docs/sunpy/data/l1_xrt20110128_013155_9.fits
 Observation date: 2011-01-28T01:31:55.932 UTC (TBR)
 Filter Wheel 1: Open 0
 Filter Wheel 2: Ti_poly 2
 Dimension: 384 384

The temperature_from_filter_ratio function has several options, mirroring the IDL routine xrt_teem.pro in SolarSoft in most respects. A simple call with no extra parameters calculates the temperature and (volume) emission measure for the two images without any binning or masking of the data.

[6]:
T_EM = temperature_from_filter_ratio(map1, map2)
T_e = T_EM.Tmap

The output of temperature_from_filter_ratio is a namedtuple of SunPy maps with attributes Tmap, EMmap, Terrmap, and EMerrmap. As with the SolarSoft IDL routine xrt_teem.pro, the output images are logs of the quantities. Tmap.data is the electron temperature, EMmap.data is the volume emission measure, Terrmap.data is a measure of the uncertainties in the temperature determined for each pixel and EMerrmap.data is the same for the emission measure. Each map has data and associated metadata. To examine the results one can use matplotlib and sunpy:

[7]:
import matplotlib.pyplot as plt
import numpy as np
from sunpy.coordinates.sun import B0, angular_radius
from sunpy.map import Map

# To avoid error messages from sunpy we add metadata to the header:
rsun_ref = 6.95700e08
hdr1 = map1.meta
rsun_obs = angular_radius(hdr1["DATE_OBS"]).value
dsun = rsun_ref / np.sin(rsun_obs * np.pi / 6.48e5)
solarb0 = B0(hdr1["DATE_OBS"]).value
hdr1["DSUN_OBS"] = dsun
hdr1["RSUN_REF"] = rsun_ref
hdr1["RSUN_OBS"] = rsun_obs
hdr1["SOLAR_B0"] = solarb0

fig = plt.figure()
# We could create a plot simply by doing T_e.plot(), but here we choose to make a linear plot of T_e
m = Map((10.0**T_e.data, T_e.meta))
m.plot(title="Derived Temperature", vmin=2.0e6, vmax=1.2e7, cmap="turbo")
m.draw_limb()
m.draw_grid(linewidth=2)
cb = plt.colorbar(label="T (K)")
_images/notebooks_data_analysis_Using_temperature_from_filter_ratio_13_0.png

See the temperature_from_filter_ratio.py script for more information. Among the options are verbose output, binning the data by an integer factor (to increase the signal to noise), specifying a temperature range to examine, providing a mask for excluding regions of the images from the analysis, and setting error thresholds on the temperature and photon noise that differ from the default values.

These data were analyzed by Guidoni et al. (2015, ApJ 800, 54). See also Narukage et al. (2014, Solar Phys. 289, 1029).

[ ]:

Bibliography

[1]

U. Feldman. Elemental abundances in the upper solar atmosphere . Physica Scripta, 46(3):202–220, 2014. doi:10.1088/0031-8949/46/3/002.

[2]

A. Fludra and J. T. Schmelz. The absolute coronal abundances of sulfur, calcium, and iron from Yohkoh-BCS flare spectra. Astronomy & Astrophysics, 348:286–294, August 1999.

[3]

L. Golub, E. Deluca, G. Austin, J. Bookbinder, D. Caldwell, P. Cheimets, J. Cirtain, M. Cosmo, P. Reid, A. Sette, M. Weber, T. Sakao, R. Kano, K. Shibasaki, H. Hara, S. Tsuneta, K. Kumagai, T. Tamura, M. Shimojo, J. McCracken, J. Carpenter, H. Haight, R. Siler, E. Wright, J. Tucker, H. Rutledge, M. Barbera, G. Peres, and S. Varisco. The X-Ray Telescope (XRT) for the Hinode Mission. Solar Physics, 243(1):63–86, 2007. doi:10.1007/s11207-007-0182-1.

[4]

N. Grevesse, M. Asplund, and A. J. Sauval. The Solar Chemical Composition. \ssr , 130(1-4):105–114, June 2007. doi:10.1007/s11214-007-9173-7.

[5]

T. Kosugi, K. Matsuzaki, T. Sakao, T. Shimizu, Y. Sone, S. Tachikawa, T. Hashimoto, K. Minesugi, A. Ohnishi, T. Yamada, S. Tsuneta, H. Hara, K. Ichimoto, Y. Suematsu, M. Shimojo, T. Watanabe, S. Shimada, J. M. Davis, L. D. Hill, J. K. Owens, A. M. Title, J. L. Culhane, L. K. Harra, G. A. Doschek, and L. Golub. The Hinode (Solar-B) Mission: An Overview. Solar Physics, 243(1):3–17, 2007. doi:10.1007/s11207-007-9014-6.

[6]

N. Narukage, T. Sakao, R. Kano, H. Hara, M. Shimojo, T. Bando, F. Urayama, E. DeLuca, L. Golub, M. Weber, P. Grigis, J. Cirtain, and S. Tsuneta. Coronal-Temperature-Diagnostic Capability of the Hinode/X-Ray Telescope Based on Self-Consistent Calibration. Solar Physics, 269(1):169–236, 2011. doi:10.1007/s11207-010-9685-2.

[7]

N. Narukage, T. Sakao, R. Kano, M. Shimojo, A. Winebarger, M. Weber, and K. Reeves. Coronal-Temperature-Diagnostic Capability of the Hinode/X-Ray Telescope Based on Self-consistent Calibration. II. Calibration with On-Orbit Data . Solar Physics, 289(3):1029–1042, 2014. doi:10.1007/s11207-013-0368-7.

Glossary

Contamination refers to the accumulation of contaminating material on the XRT CCD and focal plane filters (FPFs), which results in a decrease in sensitivity. Refer to Section 2.5.3 Contamination in the SolarSoft XRT Analysis Guide in the SolarSoft XRT Analysis Guide for more information about the XRT contamination.

DN

Data number (DN) per unit.

Solar-Emission-Spectra

Solar emission spectra are a collection of plasma emission spectra corresponding to different temperatures. They provide information about the emitted radiation at various temperatures.

Temperature response

Temperature response refers to the instrument’s temperature response function for a specific filter channel. Units measured in DN cm5 s−1 pix-1.

Changelog

This document lists the changes made during each release of XRTpy, including bug fixes and changes to the application programming interface (API).

Unreleased changes

XRTpy v0.4.1.dev12+g660a539 (2024-02-23)

Deprecations and Removals
  • Removed support for Python 3.8. XRTpy now requires Python 3.9 or newer. (#139)

Improved Documentation
  • Added Sphinx extensions to allow code blocks in the documentation to be copied and to create links to pages that show source code of different objects. (#187)

XRTpy v0.4.0 (2023-10-10)

Deprecations and Removals

  • Remove the light-leak files from the repository in favor of pulling them from one of two possible SolarSoft mirrors with the goal of reducing the total repository size. (#178, #180)

Documentation

  • Updated Python example notebooks to ensure a user-friendly and accessible experience. (#164)

  • Revised and improved all text/documentation sections of XRTpy to ensure accuracy, clarity, and completeness. (#165)

Internal modifications and improvements

  • Modified ~xrtpy.response.xrt_deconvolve to use the Sunpy data manager to download the data files. (#172)

  • Updated the Read the Docs configuration file. (#173)

  • Removed psf files after a new improvement in downloading them as part of the XRTpy package. (#177)

  • Updated the xrt_contam_on_ccd.geny file with new CCD contamination values. (#191)

  • Moved xrt_deconvolve and xrt_remove_lightleak from the util directory to a new directory named image_correction, and removed the xrt_ prefix from their names. Renamed xrt_teem to temperature_from_filter_ratio. Updated all tests and notebooks to reflect the name and directory changes. (#196)

XRTpy v0.3.0 (2023-03-31)

Deprecations and Removals

  • Modified ~xrtpy.response.xrt_teem.xrt_teem to return a ~collections.namedtuple of SunPy maps. (#148)

Features

  • New routine ~xrtpy.util.xrt_deconvolve.xrt_deconvolve, uses the Hinode XRT point spread function and the Richardson-Lucy algorithm to deconvolve (sharpen) an XRT image. (#145)

  • New functionality, ~xrtpy.util.xrt_remove_lightleak.xrt_remove_lightleak for subtracting light leak (visible stray light) image from XRT synoptic composite images. (#151)

Improved Documentation

  • Updated Python requirements for packages used in XRTpy. (#139, #137)

  • Redeveloped the XRTpy GitHub issue templates. (#154)

  • Updated the bibliography and ~xrtpy.response.xrt_teem.xrt_teem example notebook. (#158)

  • Updated the XRT contamination data file, which is now up-to-date through 2023-05-20. (#160)

XRTpy v0.2.0 (2023-03-16)

Deprecations and Removals

  • Fixed time handling in contamination calculations using astropy.time. (#104)

Features

  • Added routine xrt_teem to derive temperatures and emission measures from pairs of images using the filter ratio method. (#89)

Bug Fixes

  • Addressed and fixed the temperature response nan calculations output. (#111)

Improved Documentation

  • Updated temperature response example notebook. (#94)

  • Updated effective area example notebook. (#102)

  • Added a changelog. (#128)

Communication Routes

XRTpy has several methods of contact to get direct intel of XRTpy’s current works, reporting bugs, giving feedback, and asking questions. Please direct any comments, questions, or suggestions to xrtpy@cfa.harvard.edu.

Feedback

We appreciate any feedback describing your experience using XRTpy. We welcome other methods and ideas towards the development of XRTpy. You may contact us via email or through GitHub Hinode XRT.

Bug Encounters

In the event that you come across a direct XRTpy error, flaw, or unexpected operation, please report it to us directly via email or by creating a GitHub-issue.

Contributor Guide

Installation for Development

This page has not yet been written.

Contribution Workflow

This page has not yet been written.

Updating XRTpy Testing Data from SolarSoft IDL

This page is designed for an XRTpy maintainer to update testing text files from the Solar Software Interactive Data Language (IDL) to the XRTpy testing environment. The process involves running IDL scripts with current dates to create new test files. Subsequently, move these newly created testing files to the correct directories in XRTpy. Finally, run the testing code to test the newly updated files. Consistent testing is crucial for XRTpy to produce accurate data for any requested date and time.

IDL Testing Scripts

There are two IDL testing scripts written to generate the testing text files. These IDL scripts are written in IDL format and are intended to be run in Solar Software Interactive Data Language (IDL). You can find the IDL scripts at xrtpy/IDL_scripts/IDL_test_scripts. There are scripts for effective area and temperature response. These scripts contain information on the necessary changes to execute the code.

IDL Testing Data for Channels

After creating new testing text files by running the IDL scripts on your local machine, transfer them to the correct directories in XRTpy. Within xrtpy/xrtpy/response/test/data, you’ll find two additional folders: effective_area_IDL_testing_files and temperature_response_IDL_testing_files. Place the testing files into their corresponding folders.

Moving up a directory to xrtpy/xrtpy/response/test/data/effective_area_IDL_testing_files or temperature_response_IDL_testing_files, you’ll find additional folders for each filter. Place the testing files into their respective filter folders. Each filter folder contains text files with specific title formatting. It’s important to maintain consistent title naming conventions when updating new testing files; the format should be (filter_name_first_abbreviation)_(filter_name_second_abbreviation)_YYYYMMDD_effective_area.txt. The text files contain header information such as Filter, observation_data, and two rows of data: wavelength and effective area. Properly formatting these text files is crucial for a successful test run. The IDL script will format this correctly.

The process involves placing the new test text files into the correct folder (effective area or temperature response), followed by placing them into the correct filter folder. Ensure the title of the text file is in the correct format and verify that the text file’s format is consistent.

The purpose is to add new testing files to the existing ones. This step can later be automated by creating code to run monthly.

IDL Testing Data for Effective Area

The IDL testing data for the effective area is located in response/test/data/effective_area_testing_files. This directory contains a folder for each corresponding filter channel, e.g., Al-mesh, Al-med, Al-poly, Al-thick, Be-med, Be-thick, Be-thin, C-poly, Ti-poly. Each filter folder contains text files with header information like Filter, observation_data, and two rows of data: temperature and effective area. Follow “IDL Testing Scripts & IDL Test Files Relocation” to test the effective area. Once files are correctly placed, run pytest test_effective_area.py to test. All results should pass for a successful run. The purpose is to add new testing files to the existing ones.

IDL Testing Data for Temperature Responses

The IDL testing data for temperature responses is located in test/data/temperature_responses_testing_files. This directory contains a folder for each corresponding filter channel, e.g., Al-mesh, Al-med, Al-poly, Al-thick, Be-med, Be-thick, Be-thin, C-poly, Ti-poly. Each filter folder contains text files with header information like Filter, observation_data, and two rows of data: temperature and temperature responses. Follow “IDL Testing Scripts & IDL Test Files Relocation” to test the temperature responses. Run pytest -v test_temperature_response.py to test. All results should pass for a successful run. The purpose is to add new testing files to the existing ones.

Release Guide

This page has not yet been written.

Indices and tables