How to set up a launch script for TipTop?
Run a TipTop simulation and display PSFs
Simplest way
As explained in the Quickstart section, to run a simulation with TipTop, you need:
➡️ a launch script which:
-
Loads the simulation parameters from a .ini file (e.g., minimalPar.ini)
-
Initializes the necessary modules
-
Starts the simulation
The simplest file to launch a simulation looks like this (TIPTOP-EXAMPLE.py
,
available in the examples/
folder of our GitHub repository):
from tiptop.tiptop import *
overallSimulation("./", "minimalPar", './', 'test')
where:
- The first and second arguments of
overallSimulation
are the path to the folder containing the input.ini
file and the name of that file (without the extension). - The third and fourth arguments specify where to save the output results (in
.fits
format) and and the name of the resulting.fits
file.
A detailed documentation on the overallSimulation
function is available below.
More complete launch file
Below is an example of a more advanced launch file. It runs a simulation
for the ERIS instrument (see here) and extracts key outputs, including PSFs
and performance metrics (e.g., Strehl Ratio (SR), Full Width at Half Maximum (FWHM)) from the output .fits
file
(see Simulation Output below).
It also generates log-scaled intensity plots of the PSFs and a semi-logarithmic radial profile plot.
✅ You can adapt this script by changing the input/output paths and filenames to match your configuration.
The full example script is available for download
here📥.
Example run file: TIPTOP_RUN.py
"""
Created on Mon Jun 23 10:58:33 2025
Run a TIPTOP simulation and display PSFs
@author: lmazzolo
"""
#%% Import necessary libraries
from tiptop.tiptop import *
from astropy.io import fits
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np
#%% Define input and output paths and filenames
#💡 You should customize these paths and filenames according to your setup
path_in = "./" # Path to the folder containing your .ini parameter file
path_out = "./" # Path where output files will be saved
file_in = "ERIS_SCAO_NGS" # Name of the input parameter file (without extension)
file_out = "ERIS_SCAO_NGS" # Name to use for the output files
#%% Define a helper function to extract metrics from the FITS header
def get_metric(header, metric_name, index=0):
"""
Retrieve a value from the FITS header with a formatted key.
:param header: FITS header
:param metric_name: name of the metric (e.g., 'SR')
:param index: index of the metric (default 0)
:return: value or None if key not found
"""
key = f"{metric_name}{index:04d}"
return header.get(key)
#%% Run the TIPTOP simulation
overallSimulation(path_in, file_in,
path_out, file_out)
#%% Open the resulting FITS file and extract data
with fits.open(path_out + file_out + '.fits') as hdul:
hdul.info()
psf_ao = hdul[1].data[0,...] # AO-corrected PSF
psf_turb = hdul[2].data # Seeing-limited PSF
psf_dl = hdul[3].data # Diffraction-limited PSF
profiles = hdul[4].data # PSF profile
header = hdul[1].header # FITS header for metadata
# Extract useful parameters
wvl = float(header.get("WL_NM")) # Wavelength in nm
pix_mas = float(header.get("PIX_MAS")) # Pixel scale in milliarcseconds
sr = get_metric(header, "SR") # Strehl ratio
fwhm = get_metric(header, "FWHM") # FWHM in milliarcsecond
# Print key metrics
print("Pixel scale [mas]:", pix_mas)
print("Strehl Ratio:", sr)
print("FWHMs [mas]:", fwhm)
#%% Normalize the PSFs so total flux = 1
psf_ao /= np.sum(psf_ao)
psf_dl /= np.sum(psf_dl)
psf_turb /= np.sum(psf_turb)
#%% Create axis in arcseconds
nx = psf_ao.shape[0]
axis = np.linspace(-nx//2, nx//2, nx) * pix_mas * 1e-3
#%% Plot the PSFs
# Compute dynamic normalization based on the AO PSF
psf_max = psf_ao.max()
vmax = psf_max
vmin = psf_max * 1e-6 # Adjust dynamic range: show down to 1 millionth of max
norm = LogNorm(vmin=vmin, vmax=vmax) # Set log scale for display
plt.figure(1, figsize=(20,5))
plt.suptitle(r'$\lambda_{\mathrm{science}} = %d$ nm' % int(wvl), y=1)
plt.subplots_adjust(top=0.85)
def plot_psf(psf, title, position):
"""Plot a PSF in a given subplot position."""
plt.subplot(1, 3, position)
plt.imshow(psf, norm=norm, cmap='Spectral_r',
extent=[axis[0], axis[-1], axis[0], axis[-1]])
plt.title(title, pad=10)
plt.xlabel('[arcsec]')
if position == 1:
plt.ylabel('[arcsec]', labelpad=10)
else:
plt.ylabel('')
plt.colorbar(fraction=0.046)
plot_psf(psf_ao, f'AO (SR={sr*100:.1f}%, FWHM={fwhm:.1f}mas)', 1)
plot_psf(psf_dl, 'Diffraction', 2)
plot_psf(psf_turb, 'Open loop', 3)
#%% Plot the radial profile
profiles = np.squeeze(profiles)
print(f"Profile shape after squeeze: {profiles.shape}")
radii = np.arange(profiles.shape[1])
plt.figure(figsize=(8, 6))
plt.plot(radii, profiles[1, :], label='AO profile')
max_radius = radii.max()
plt.xlim(0, 0.75 * max_radius)
plt.xlabel('Radial distance (pixels)')
plt.ylabel('Normalized intensity')
plt.yscale("log")
plt.title(f'Radial profile - AO corrected PSF - @{int(wvl)} nm')
plt.legend()
plt.grid(True)
✏️Note: Results for the different AO instruments presented here
were obtained by running this script with the corresponding provided .ini
files.
Simulation Output
The output of a TipTop simulation consists of Point Spread Functions (PSFs) computed using the parameters specified in your .ini
file.
If the doPlot
parameter of the overallSimulation function is set to True
, the following PSFs will be displayed after the simulation runs:
- The AO-corrected PSF(s)
- The seeing-limited PSF
- The diffraction limited PSF
These PSFs are also saved in a .fits
file for further analysis and post-processing.
FITS File Structure & Contents
The FITS file contains multiple HDUs (Header/Data Units), each storing different types of data related to the PSFs generated during the simulation. The content is organized as follows:
- HDU 0 – PRIMARY
Contains metadata about the simulation, the instrument, and observational parameters. It does not contain image data but provides essential contextual information. - HDU 1 – AO-Corrected PSF
Stores the cube of AO-corrected PSFs as a multi-dimensional image array with dimensions (FieldOfView
,FieldOfView
,Nsrc
,Nwvl
), whereFieldOfView
corresponds to the camera’s field of view in pixels as defined in the[sensor_science]
section of your.ini
file,Nsrc
is the number of science sources, andNwvl
is the number of wavelengths specified in theWavelength
parameter of the[sources_science]
section. - HDU 2 – Seeing-Limited PSF
Contains the seeing-limited (open-loop) PSF in a 2D image array of size (FieldOfView
,FieldOfView
). - HDU 3 – Diffraction-Limited PSF
Contains the diffraction-limited PSF, also stored as a 2D image array of size (FieldOfView
,FieldOfView
). - HDU 4 – PSDs (if
savePSDs=True
)
Contains the Power Spectral Density (PSD), stored as a 3D array. - HDU 4 or 5 – Final PSFs Radial Profiles
Contains the 1D radial profiles of the PSFs, stored as an 3D array.
✏️Note: The HDU number depends on whether the PSDs are saved.
Here is an example FITS structure produced with the minimalPar.ini configuration:
No. Name Ver Type Cards Dimensions Format
0 PRIMARY 1 PrimaryHDU 84 ()
1 1 ImageHDU 21 (256, 256, 1) float64 #AO-corrected PSFs
2 1 ImageHDU 10 (256, 256) float64 #Open-loop PSF
3 1 ImageHDU 10 (256, 256) float64 #Diffraction limited PSF
4 1 ImageHDU 11 (256, 256, 1) float64 #High Order PSD (if saved)
5 1 ImageHDU 11 (128, 1, 2) float64 #PSFs profiles
✏️Note: Results for the different AO instruments presented here
Note: By default, the FITS file header includes the SR and FWHM values for each PSF (the addSrAndFwhm
parameter of the overallSimulation
function is set to True
by default).
To retrieve and display the SR, FWHM and Encircled energy metrics directly in your terminal, set the
returnMetrics
option to True
(see the documentation on the overallSimulation function below).
⚠️ If returnMetrics
is set to True
, the FITS file is not saved.
OverallSimulation function documentation
tiptop.overallSimulation runs a complete TipTop simulation based on an input parameter file.
The function accepts several optional arguments to enable or disable specific features and select desired outputs.
All the parameters that can be passed as arguments are listed and explained below:
Parameters:
-
path2param (str) – required, path to the parameter file.
-
paramFileName (str) – required, name of the parameter file to be used without the extention.
-
outpuDir – required, path to the folder in which to write the output.
-
doConvolve (bool) – optional default: True, if you want to use the natural convolution operation set to True.
-
doPlot (bool) – optional default: False, if you want to see the result in python set this to True.
-
verbose (bool) – optional default: False, If you want all messages set this to True
-
returnRes (bool) – optional default: False, The function will return the result in the environment if set to True, else it saves the result only in a .fits file.
-
returnMetrics (bool) – optional default: False, The function will return Strehl Ratio, fwhm and encircled energy within eeRadiusInMas if set to True
-
addSrAndFwhm (bool) – optional default: True, The function will add in the header of the fits file SR anf FWHM for each PSF.
-
verbose – optional default: False, If you want all messages set this to True.
-
getHoErrorBreakDown (bool) – optional default: False, If you want HO error breakdown set this to True.
-
ensquaredEnergy (bool) – optional default: False, If you want ensquared energy instead of encircled energy set this to True.
-
eeRadiusInMas (float) – optional default: 50, used together with returnMetrics, radius used for the computation of the encirlced energy (if ensquaredEnergy is selected, this is half the side of the square)
-
savePSDs (bool) – optional default: False, If you want to save PSD in the output fits file set this to True.
-
saveJson (bool) – optional default: False, If you want to save the PSF profile in a json file
-
gpuIndex (int) – optional default: 0, Target GPU index where the simulation will be run
⚠️ Note: if returnMetrics
is set to True
, the FITS file is not saved.