Source code for exosim.plots.utils
from copy import deepcopy
import h5py
import matplotlib as mpl
import matplotlib.colors as mcolors
import numpy as np
from astropy.table import Table
def _create_ordered_cmap(
map_name: str,
roll: int | None = None,
delete: int | None = None,
change: list[tuple[int, int]] | None = None,
) -> mcolors.ListedColormap:
"""
Create an ordered colormap based on a given colormap name.
Parameters:
- map_name (str): The name of the colormap to use.
- roll (int, optional): The number of positions to roll the colormap colors. Defaults to None.
- delete (int, optional): The index of the color to delete from the colormap. Defaults to None.
- change (list[tuple[int, int]], optional): A list of pairs of indices to swap colors in the colormap. Defaults to None.
Returns:
- cmap (matplotlib.colors.ListedColormap): The created ordered colormap.
"""
pastel1_cmap = mpl.colormaps.get_cmap(map_name)
pastel1_colors = pastel1_cmap(np.linspace(0, 1, pastel1_cmap.N))
pastel1_colors_hsv = np.array(
[mcolors.rgb_to_hsv(color[:3]) for color in pastel1_colors]
)
sorted_indices = np.argsort(pastel1_colors_hsv[:, 0])
sorted_colors = pastel1_colors[sorted_indices]
reversed_colors = sorted_colors[::-1]
if roll is not None:
reversed_colors = np.roll(reversed_colors, roll, axis=0)
if delete is not None:
if isinstance(delete, list):
for del_ in delete:
reversed_colors = np.delete(reversed_colors, del_, axis=0)
else:
reversed_colors = np.delete(reversed_colors, delete, axis=0)
if change is not None:
for couple in change:
val1 = deepcopy(reversed_colors[couple[0]])
reversed_colors[couple[0]] = deepcopy(reversed_colors[couple[1]])
reversed_colors[couple[1]] = val1
return mcolors.ListedColormap(reversed_colors)
[docs]
def prepare_channels_list(
input_table,
) -> tuple[np.ndarray, mpl.colors.Normalize]:
"""
Prepare the list of channels and the normalization object for plotting,
using a table with 'ch_name' and 'wavelength' columns.
Parameters
----------
input_table : astropy.table.Table or QTable
Table containing at least 'ch_name' and 'wavelength' columns.
Returns
-------
Tuple[np.ndarray, matplotlib.colors.Normalize]
The sorted array of channel names and the normalization object.
"""
# Check if input_table is actually a table
if isinstance(input_table, str):
with h5py.File(input_table, "r") as f:
if "channels" in f:
channels_path = f["channels"]
elif "targets" in f:
targets = list(f["targets"].keys())
channels_path = f["targets"][targets[0]]["channels"]
else:
raise ValueError("No channels or targets found in the HDF5 file.")
channels_wl = []
channels = np.array(list(channels_path.keys()))
for channel_name in channels:
metadata = channels_path[channel_name]["focal_plane/metadata"]
wl_min = metadata["wl_min"]["value"][()]
channels_wl.append(wl_min)
# Sort channels by their minimum wavelength
id_ = np.argsort(channels_wl)
channels_sorted = channels[id_]
norm = mpl.colors.Normalize(vmin=0.0, vmax=len(channels_sorted))
if isinstance(input_table, Table):
# Get unique channel names
channels = np.unique(input_table["ch_name"])
# For each channel, get the minimum wavelength (or another representative value)
channels_wl = []
# Try both 'wavelength' and 'Wavelength' column names
wl_col = "wavelength" if "wavelength" in input_table.colnames else "Wavelength"
for channel_name in channels:
mask = input_table["ch_name"] == channel_name
wl_min = np.min(input_table[wl_col][mask])
channels_wl.append(wl_min.value)
# Sort channels by their minimum wavelength
id_ = np.argsort(channels_wl)
channels_sorted = channels[id_]
norm = mpl.colors.Normalize(vmin=0.0, vmax=len(channels_sorted))
return channels_sorted, norm
[docs]
def find_channels_position(input_file: str) -> str:
"""
Find the positions of the specified channels in the HDF5 file.
Parameters
----------
input_file : str
Path to the HDF5 file.
Returns
-------
str
The path to the channels in the HDF5 file.
"""
with h5py.File(input_file, "r") as f:
if "channels" in f:
channels_path = "channels"
elif "targets" in f:
targets = list(f["targets"].keys())
channels_path = f"targets/{targets[0]}/channels"
return channels_path