
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.
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 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!

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:
- Filter Configuration
- Filter position
- Filter Wheel 1:
Open
Aluminum Polyimide (Al-poly)
Carbon Polyimide (C-poly)
Beryllium Thin (Be-thin)
Beryllium Medium (Be-med)
Aluminum Medium (Al-med)
- Filter Wheel 2:
Open
Aluminum Mesh (Al-mesh)
Titanium Polyimide (Ti-poly)
G-band
Aluminum Thick (Al-thick)
Beryllium Thick (Be-thick)
- 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.
- 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
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()

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
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]:
We can even create Quantity objects that are explicitly dimensionless.
[8]:
3 * u.dimensionless_unscaled
[8]:
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]:
[10]:
[2, 3, 4] * u.m / u.s
[10]:
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]:
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
Hα = balmer_series[0]
print(Hα)
656.279 nm
[16]:
np.max(balmer_series)
[16]:
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]:
[18]:
velocity.to(u.m / u.s)
[18]:
The si and cgs attributes convert the Quantity to SI or CGS units, respectively.
[19]:
velocity.si
[19]:
[20]:
velocity.cgs
[20]:
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]:
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]:
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]:
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]:
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
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()

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
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()

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()

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()

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()

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)")

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
U. Feldman. Elemental abundances in the upper solar atmosphere . Physica Scripta, 46(3):202–220, 2014. doi:10.1088/0031-8949/46/3/002.
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.
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.
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.
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.
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.
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
Documentation
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
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.