TEMPS / notebooks /Colourspace.py
Laura Cabayol Garcia
running precommit
668e440
raw
history blame
10.2 kB
# ---
# jupyter:
# jupytext:
# text_representation:
# extension: .py
# format_name: light
# format_version: '1.5'
# jupytext_version: 1.16.2
# kernelspec:
# display_name: temps
# language: python
# name: temps
# ---
# # FIGURE COLOURSPACE IN THE PAPER
# %load_ext autoreload
# %autoreload 2
import pandas as pd
import numpy as np
import os
from astropy.io import fits
from astropy.table import Table
import torch
from pathlib import Path
# matplotlib settings
from matplotlib import rcParams
import matplotlib.pyplot as plt
rcParams["mathtext.fontset"] = "stix"
rcParams["font.family"] = "STIXGeneral"
from temps.archive import Archive
from temps.utils import nmad
from temps.temps_arch import EncoderPhotometry, MeasureZ
from temps.temps import TempsModule
def estimate_som_map(df, plot_arg="z", nx=40, ny=40):
"""
Estimate a Self-Organizing Map (SOM) visualization from a DataFrame.
Parameters:
- df (pandas.DataFrame): Input DataFrame containing data for SOM estimation.
- plot_arg (str, optional): Column name to be used for plotting. Default is 'z'.
- nx (int, optional): Number of cells along the X-axis. Default is 40.
- ny (int, optional): Number of cells along the Y-axis. Default is 40.
Returns:
- som_data (numpy.ndarray): Estimated SOM visualization data.
"""
x_cells = np.arange(0, nx)
y_cells = np.arange(0, ny)
index_cell = np.arange(nx * ny)
cells = np.array(np.meshgrid(x_cells, y_cells)).T.reshape(-1, 2)
cells = pd.DataFrame(
np.c_[cells[:, 0], cells[:, 1], index_cell],
columns=["x_cell", "y_cell", "cell"],
)
if plot_arg == "count":
som_vis = (
df.groupby("cell")["z"]
.count()
.reset_index()
.rename(columns={f"z": "plot_som"})
)
else:
som_vis = (
df.groupby("cell")[f"{plot_arg}"]
.mean()
.reset_index()
.rename(columns={f"{plot_arg}": "plot_som"})
)
som_data = som_vis.merge(cells, on="cell")
som_data = som_data.pivot(index="x_cell", columns="y_cell", values="plot_som")
return som_data
def plot_som_map(som_data, plot_arg="z", vmin=0, vmax=1):
"""
Plot the Self-Organizing Map (SOM) data.
Parameters:
- som_data (numpy.ndarray): The SOM data to be visualized.
- plot_arg (str, optional): The column name to be plotted. Default is 'z'.
- vmin (float, optional): Minimum value for color scaling. Default is 0.
- vmax (float, optional): Maximum value for color scaling. Default is 1.
Returns:
None
"""
plt.imshow(
som_data, vmin=vmin, vmax=vmax, cmap="viridis"
) # Choose an appropriate colormap
plt.colorbar(label=f"{plot_arg}") # Add a colorbar with a label
plt.xlabel(r"$x$ [pixel]", fontsize=14) # Add an appropriate X-axis label
plt.ylabel(r"$y$ [pixel]", fontsize=14) # Add an appropriate Y-axis label
plt.show()
# ### LOAD DATA
# define here the directory containing the photometric catalogues
parent_dir = Path(
"/data/astro/scratch/lcabayol/insight/data/Euclid_EXT_MER_PHZ_DC2_v1.5"
)
modules_dir = Path("../data/models/")
filename_calib = "euclid_cosmos_DC2_S1_v2.1_calib_clean.fits"
filename_valid = "euclid_cosmos_DC2_S1_v2.1_valid_matched.fits"
# +
filename_valid = "euclid_cosmos_DC2_S1_v2.1_valid_matched.fits"
hdu_list = fits.open(parent_dir / filename_valid)
cat = Table(hdu_list[1].data).to_pandas()
cat = cat[cat["FLAG_PHOT"] == 0]
cat = cat[cat["mu_class_L07"] == 1]
cat = cat[(cat["z_spec_S15"] > 0) | (cat["photo_z_L15"] > 0)]
cat = cat[cat["MAG_VIS"] < 25]
# -
ztarget = [
cat["z_spec_S15"].values[ii]
if cat["z_spec_S15"].values[ii] > 0
else cat["photo_z_L15"].values[ii]
for ii in range(len(cat))
]
specz_or_photo = [
0 if cat["z_spec_S15"].values[ii] > 0 else 1 for ii in range(len(cat))
]
ID = cat["ID"]
VISmag = cat["MAG_VIS"]
zsflag = cat["reliable_S15"]
photoz_archive = Archive(
path_calib=parent_dir / filename_calib,
path_valid=parent_dir / filename_valid,
only_zspec=False,
)
f = photoz_archive._extract_fluxes(catalogue=cat)
col = photoz_archive._to_colors(f)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# +
dfs = {}
for il, lab in enumerate(["z", "L15", "DA"]):
nn_features = EncoderPhotometry()
nn_features.load_state_dict(
torch.load(modules_dir / f"modelF_{lab}.pt", map_location=torch.device("cpu"))
)
nn_z = MeasureZ(num_gauss=6)
nn_z.load_state_dict(
torch.load(modules_dir / f"modelZ_{lab}.pt", map_location=torch.device("cpu"))
)
temps_module = TempsModule(nn_features, nn_z)
z, pz, odds = temps_module.get_pz(input_data=torch.Tensor(col), return_pz=True)
# Create a DataFrame with the desired columns
df = pd.DataFrame(
np.c_[ID, VISmag, z, odds, ztarget, zsflag, specz_or_photo],
columns=["ID", "VISmag", "z", "odds", "ztarget", "zsflag", "S15_L15_flag"],
)
# Calculate additional columns or operations if needed
df["zwerr"] = (df.z - df.ztarget) / (1 + df.ztarget)
# Drop any rows with NaN values
df = df.dropna()
# Assign the DataFrame to a key in the dictionary
dfs[lab] = df
# -
# ### LOAD TRAINED MODELS AND EVALUATE PDFs AND REDSHIFT
# define here the directory containing the photometric catalogues
parent_dir = Path(
"/data/astro/scratch/lcabayol/insight/data/Euclid_EXT_MER_PHZ_DC2_v1.5"
)
modules_dir = Path("../data/models/")
df_z = dfs["z"]
df_z_DA = dfs["DA"]
# ##### LOAD TRAIN SOM ON TRAINING DATA
df_som = pd.read_csv(parent_dir / "som_dataframe.csv", header=0, sep=",")
df_z = df_z.merge(df_som, on="ID")
df_z_DA = df_z_DA.merge(df_som, on="ID")
# ##### APPLY CUTS FOR DIFFERENT SAMPLES
df_zspec = df_z[(df_z.S15_L15_flag == 0) & (df_z.zsflag == 1)]
df_l15 = df_z[(df_z.ztarget > 0)]
df_l15_DA = df_z_DA[(df_z_DA.ztarget > 0)]
df_l15_euclid = df_z[(df_z.VISmag < 24.5) & (df_z.z > 0.2) & (df_z.z < 2.6)]
df_l15_euclid_cut = df_l15_euclid[
df_l15_euclid.odds > df_l15_euclid["odds"].quantile(0.2)
]
df_l15_euclid_da = df_z_DA[
(df_z_DA.VISmag < 24.5) & (df_z_DA.z > 0.2) & (df_z_DA.z < 2.6)
]
df_l15_euclid_cut_da = df_l15_euclid_da[
df_l15_euclid_da.odds > df_l15_euclid["odds"].quantile(0.2)
]
# ## MAKE SOM PLOT
from mpl_toolkits.axes_grid1 import make_axes_locatable
# +
fig, axs = plt.subplots(
6,
4,
figsize=(13, 15),
sharex=True,
sharey=True,
gridspec_kw={"hspace": 0.05, "wspace": 0.06},
)
# Plot in the top row (axs[0, i])
# top row, spectroscopic sample
columns = ["ztarget", "z", "zwerr", "count"]
titles = [r"$z_{true}$ (A)", r"$z$ (B)", r"$z_{\rm error}$ (C)", "Counts"]
limits = [[0, 4], [0, 4], [-0.5, 0.5], [0, 50]]
for ii in range(4):
som_data = estimate_som_map(df_zspec, plot_arg=columns[ii], nx=40, ny=40)
im = axs[0, ii].imshow(
som_data, vmin=limits[ii][0], vmax=limits[ii][1], cmap="viridis"
) # Choose an appropriate colormap
axs[0, ii].set_title(f"{titles[ii]}", fontsize=18)
if ii == 0:
axs[0, 0].set_ylabel(r"$y$", fontsize=14)
elif ii == 1:
cbar_ax = fig.add_axes([0.49, 0.11, 0.01, 0.77])
fig.colorbar(im, cax=cbar_ax)
elif ii == 2:
cbar_ax = fig.add_axes([0.685, 0.11, 0.01, 0.77])
fig.colorbar(im, cax=cbar_ax)
elif ii == 3:
cbar_ax = fig.add_axes([0.885, 0.11, 0.01, 0.77])
fig.colorbar(im, cax=cbar_ax)
for jj in range(4):
som_data = estimate_som_map(df_l15, plot_arg=columns[jj], nx=40, ny=40)
im = axs[1, jj].imshow(
som_data, vmin=limits[jj][0], vmax=limits[jj][1], cmap="viridis"
) # Choose an appropriate colormap
# axs[1, jj].set_title(f'{titles[jj]}', fontsize=14)
# axs[1, jj].set_xlabel(r'$x$', fontsize=14)
for kk in range(4):
som_data = estimate_som_map(df_l15_DA, plot_arg=columns[kk], nx=40, ny=40)
im = axs[2, kk].imshow(
som_data, vmin=limits[kk][0], vmax=limits[kk][1], cmap="viridis"
) # Choose an appropriate colormap
# axs[2, kk].set_title(f'{titles[kk]}', fontsize=14)
# axs[2, kk].set_xlabel(r'$x$', fontsize=14)
for rr in range(4):
som_data = estimate_som_map(df_l15_euclid_da, plot_arg=columns[rr], nx=40, ny=40)
im = axs[3, rr].imshow(
som_data, vmin=limits[rr][0], vmax=limits[rr][1], cmap="viridis"
) # Choose an appropriate colormap
# axs[3, rr].set_title(f'{titles[rr]}', fontsize=14)
# axs[3, rr].set_xlabel(r'$x$', fontsize=14)
for ll in range(4):
som_data = estimate_som_map(df_l15_euclid_cut, plot_arg=columns[ll], nx=40, ny=40)
im = axs[4, ll].imshow(
som_data, vmin=limits[ll][0], vmax=limits[ll][1], cmap="viridis"
) # Choose an appropriate colormap
# axs[4, ll].set_title(f'{titles[ll]}', fontsize=14)
axs[4, ll].set_xlabel(r"$x$", fontsize=14)
for ll in range(4):
som_data = estimate_som_map(
df_l15_euclid_cut_da, plot_arg=columns[ll], nx=40, ny=40
)
im = axs[5, ll].imshow(
som_data, vmin=limits[ll][0], vmax=limits[ll][1], cmap="viridis"
) # Choose an appropriate colormap
# axs[4, ll].set_title(f'{titles[ll]}', fontsize=14)
axs[5, ll].set_xlabel(r"$x$", fontsize=14)
axs[0, 0].set_ylabel(r"$y$", fontsize=14)
axs[1, 0].set_ylabel(r"$y$", fontsize=14)
axs[2, 0].set_ylabel(r"$y$", fontsize=14)
axs[3, 0].set_ylabel(r"$y$", fontsize=14)
axs[4, 0].set_ylabel(r"$y$", fontsize=14)
axs[5, 0].set_ylabel(r"$y$", fontsize=14)
fig.text(
0.09, 0.815, r"$z_{\rm s}$ samp. (1)", va="center", rotation="vertical", fontsize=16
)
fig.text(0.09, 0.69, r"L15 samp. (2)", va="center", rotation="vertical", fontsize=16)
fig.text(
0.09, 0.56, r"L15 samp. + DA (3)", va="center", rotation="vertical", fontsize=14
)
fig.text(
0.09,
0.44,
r"$Euclid$ samp. + DA (4)",
va="center",
rotation="vertical",
fontsize=14,
)
fig.text(
0.09, 0.3, r"$Euclid$ samp. + QC (5)", va="center", rotation="vertical", fontsize=14
)
fig.text(0.09, 0.17, r"(5) + DA ", va="center", rotation="vertical", fontsize=13)
plt.savefig("SOM_colourspace.pdf", format="pdf", bbox_inches="tight", dpi=300)
# -