# Colab Setup (Run this first)
!pip install litebird_sim rich
Requirement already satisfied: litebird_sim in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (0.16.0)
Requirement already satisfied: rich in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (14.2.0)
Requirement already satisfied: asciimatics>=1.15.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (1.15.0)
Requirement already satisfied: astropy==6.1.7 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (6.1.7)
Requirement already satisfied: deprecated>=1.2.18 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (1.3.1)
Requirement already satisfied: deprecation>=2.1.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (2.1.0)
Requirement already satisfied: ducc0>=0.38.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (0.39.1)
Requirement already satisfied: h5py>=3.9 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (3.15.1)
Requirement already satisfied: healpy>=1.18.1 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (1.18.1)
Requirement already satisfied: jinja2>=3.1 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (3.1.6)
Requirement already satisfied: jplephem>=2.22 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (2.23)
Requirement already satisfied: libinsdb>=0.9.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (0.9.0)
Requirement already satisfied: markdown-katex>=202406.1035 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (202406.1035)
Requirement already satisfied: markdown>=3.9 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (3.10)
Requirement already satisfied: matplotlib>=3.10.3 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (3.10.7)
Requirement already satisfied: numba>=0.61.2 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (0.62.1)
Requirement already satisfied: numpy>=1.26.4 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (1.26.4)
Requirement already satisfied: pygithub>=2.6.1 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (2.8.1)
Requirement already satisfied: pyperclip>=1.9.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (1.11.0)
Requirement already satisfied: pysm3>=3.4.2 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (3.4.3)
Requirement already satisfied: pyyaml>=6.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (6.0.3)
Requirement already satisfied: requests>=2.32.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (2.32.5)
Requirement already satisfied: scipy>=1.14.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (1.14.1)
Requirement already satisfied: tomlkit>=0.12.1 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from litebird_sim) (0.12.5)
Requirement already satisfied: pyerfa>=2.0.1.1 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from astropy==6.1.7->litebird_sim) (2.0.1.5)
Requirement already satisfied: astropy-iers-data>=0.2024.10.28.0.34.7 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from astropy==6.1.7->litebird_sim) (0.2025.11.24.0.39.11)
Requirement already satisfied: packaging>=19.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from astropy==6.1.7->litebird_sim) (25.0)
Requirement already satisfied: markdown-it-py>=2.2.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from rich) (4.0.0)
Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from rich) (2.19.2)
Requirement already satisfied: pyfiglet>=0.7.2 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from asciimatics>=1.15.0->litebird_sim) (1.0.4)
Requirement already satisfied: Pillow>=2.7.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from asciimatics>=1.15.0->litebird_sim) (12.0.0)
Requirement already satisfied: wcwidth in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from asciimatics>=1.15.0->litebird_sim) (0.2.14)
Requirement already satisfied: wrapt<3,>=1.10 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from deprecated>=1.2.18->litebird_sim) (2.0.1)
Requirement already satisfied: MarkupSafe>=2.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from jinja2>=3.1->litebird_sim) (3.0.3)
Requirement already satisfied: coverage<8,>=7.3.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from libinsdb>=0.9.0->litebird_sim) (7.12.0)
Requirement already satisfied: python-dateutil<3,>=2.8.2 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from libinsdb>=0.9.0->litebird_sim) (2.9.0.post0)
Requirement already satisfied: requests-mock<2,>=1.11.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from libinsdb>=0.9.0->litebird_sim) (1.12.1)
Requirement already satisfied: types-pyyaml<7,>=6.0.12.12 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from libinsdb>=0.9.0->litebird_sim) (6.0.12.20250915)
Requirement already satisfied: six>=1.5 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from python-dateutil<3,>=2.8.2->libinsdb>=0.9.0->litebird_sim) (1.17.0)
Requirement already satisfied: charset_normalizer<4,>=2 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from requests>=2.32.0->litebird_sim) (3.4.4)
Requirement already satisfied: idna<4,>=2.5 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from requests>=2.32.0->litebird_sim) (3.11)
Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from requests>=2.32.0->litebird_sim) (2.5.0)
Requirement already satisfied: certifi>=2017.4.17 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from requests>=2.32.0->litebird_sim) (2025.11.12)
Requirement already satisfied: mdurl~=0.1 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from markdown-it-py>=2.2.0->rich) (0.1.2)
Requirement already satisfied: setuptools in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from markdown-katex>=202406.1035->litebird_sim) (80.9.0)
Requirement already satisfied: contourpy>=1.0.1 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from matplotlib>=3.10.3->litebird_sim) (1.3.3)
Requirement already satisfied: cycler>=0.10 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from matplotlib>=3.10.3->litebird_sim) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from matplotlib>=3.10.3->litebird_sim) (4.60.1)
Requirement already satisfied: kiwisolver>=1.3.1 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from matplotlib>=3.10.3->litebird_sim) (1.4.9)
Requirement already satisfied: pyparsing>=3 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from matplotlib>=3.10.3->litebird_sim) (3.2.5)
Requirement already satisfied: llvmlite<0.46,>=0.45.0dev0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from numba>=0.61.2->litebird_sim) (0.45.1)
Requirement already satisfied: pynacl>=1.4.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from pygithub>=2.6.1->litebird_sim) (1.6.1)
Requirement already satisfied: pyjwt>=2.4.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from pyjwt[crypto]>=2.4.0->pygithub>=2.6.1->litebird_sim) (2.10.1)
Requirement already satisfied: typing-extensions>=4.5.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from pygithub>=2.6.1->litebird_sim) (4.15.0)
Requirement already satisfied: cryptography>=3.4.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from pyjwt[crypto]>=2.4.0->pygithub>=2.6.1->litebird_sim) (46.0.3)
Requirement already satisfied: cffi>=2.0.0 in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from cryptography>=3.4.0->pyjwt[crypto]>=2.4.0->pygithub>=2.6.1->litebird_sim) (2.0.0)
Requirement already satisfied: pycparser in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from cffi>=2.0.0->cryptography>=3.4.0->pyjwt[crypto]>=2.4.0->pygithub>=2.6.1->litebird_sim) (2.23)
Requirement already satisfied: toml in /opt/homebrew/Caskroom/miniconda/base/envs/litebird_sim/lib/python3.13/site-packages (from pysm3>=3.4.2->litebird_sim) (0.10.2)
litebird_sim scanning and pointing#
To run this notebook, you have several options:
If you are running this under Binder, you should already be set!
If you are running this under Google Colab, be sure to run the cell with
!pip install…that is right above the title.If you are running this locally, you should first create and activate a new virtual environment with the commands
python -m venv ./my_venv source ./my_venv/bin/activate
(you can use Conda environments, if you prefer) and install Jupyter and litebird_sim in it:
pip install jupyter litebird_sim
If you have a local copy of the
litebird_simrepository cloned from litebird/litebird_sim (e.g., because you’re part of the Simulation Team!), you can use a development install instead:cd /my/local/copy/litebird_sim pip install -e .
Set up the environment#
# Using this file, we can use "import litebird_sim" even if it is not installed system-wide
We start by importing a few libraries that will be useful in this notebook.
import litebird_sim as lbs
import numpy as np
import astropy
import astropy.time
import inspect
%matplotlib inline
lbs.PTEP_IMO_LOCATION
PosixPath('/Users/luca/Documents/Universita/litebird/simteam/codes/litebird_sim/litebird_sim/default_imo/schema.json.gz')
Parameters of the simulation#
We will simulate one hour of the full 140 GHz LFT channel. Their definition will be taken from the LiteBIRD Instrument MOdel (IMO) version vPTEP (new!). See the documentation for more details about the input parameters.
telescope = "LFT"
channel = "L4-140"
start_time = astropy.time.Time("2025-01-01T00:00:00")
mission_time_hrs = 1
imo_version = "vPTEP"
# Resolution of the output maps
nside = 64
Scanning strategy#
To use the IMO bundled in litebird_sim, one needs to do the following:
# This is the folder where the final report with the results of the simulation will be saved
base_path = ".test"
imo = lbs.Imo(flatfile_location=lbs.PTEP_IMO_LOCATION)
# initializing the simulation
sim = lbs.Simulation(
base_path=base_path,
imo=imo,
start_time=start_time,
duration_s=mission_time_hrs * 3600.0,
random_seed=12345, # seed for the random number generator (MANDATORY parameter!!!)
)
The following command will take some time: it needs to compute the ephemerides of the Earth with respect to the Ecliptic reference frame and derive the orientation of the LFT instrument as a function of time for the whole duration of the simulation. This step will be needed later, when we will obtain the pointings for the detectors involved in the simulation. See the documentation for more details about the scanning strategy.
# Generate the quaternions describing how the instrument moves in the Ecliptic reference frame
sim.set_scanning_strategy(
imo_url=f"/releases/{imo_version}/satellite/scanning_parameters/", delta_time_s=1
)
# The parameter `delta_time_s` specifies how often should quaternions be computed
Once the scanning strategy has been set the class spin2ecliptic_quats contains the quaterions describing the scanning of the spin axis
print(getattr(sim.spin2ecliptic_quats, "quats").shape)
# ``(N_scanning_samples, 4)`` array
(3601, 4)
The following instructions load from the IMO the information about the instrument and the detectors used in the simulation.
# Load the definition of the instrument (MFT)
sim.set_instrument(
lbs.InstrumentInfo.from_imo(
imo,
f"/releases/{imo_version}/satellite/{telescope}/instrument_info",
)
)
When setting the instrument, the simulation acquires information about the spin-to-boresight rotation for the selected instrument, as well as any additional rotation of the boresight, if present
print(getattr(sim.instrument, "spin_boresight_angle_rad"))
print(getattr(sim.instrument, "boresight_rotangle_rad"))
0.8726646259971648
0.0
The spin to boresight angle can be easly customized initializing a new instrance of the instrument class
instrument = lbs.InstrumentInfo(
name="Instrument_A", spin_boresight_angle_rad=np.deg2rad(40.0)
)
sim.set_instrument(instrument=instrument)
We are now ready to set the hwp. For this we have an abstract container, i.e. HWP. Here we use the derved class lbs.IdealHWP
# Here we set the hwp speed
sim.set_hwp(
lbs.IdealHWP(
getattr(sim.instrument, "hwp_rpm") * 2 * np.pi / 60,
), # sets the hwp
)
The final step in computing the pointings requires specifying a list of detectors. Each detector contributes the final rotation in the pointing chain, namely the transformation from the boresight to the detector reference frame
For getting the list of detectors in a Frequeny channel we can initialize the class lbs.FreqChannelInfo using the IMo.
chinfo = lbs.FreqChannelInfo.from_imo(
url=f"/releases/{imo_version}/satellite/{telescope}/{channel}/channel_info",
imo=imo,
)
# filling dets with info and detquats with quaternions of the detectors in the channel
dets: list[lbs.DetectorInfo] = []
for n_det in chinfo.detector_names:
det = lbs.DetectorInfo.from_imo(
url=f"/releases/{imo_version}/satellite/{telescope}/{channel}/{n_det}/detector_info",
imo=imo,
)
dets.append(det)
We are now ready to create a set of «observations» providing the list of detectors we have just created
# creating one observation
(obs,) = sim.create_observations(
detectors=dets,
n_blocks_det=1,
n_blocks_time=1, # blocks different from one if parallelizing
)
So, here comes the part where we need to simulate the pointings. Much of the work has already been done, as the ephemerides were already computed in the call to sim.set_scanning_strategy (see above), but this step is going to take its time too, because we are now deriving the pointings for each detector and store them in the list pointings.
The first step is done by sim.prepare_pointings():
sim.prepare_pointings()
This method initializes a function in each observation that allows to compute the pointing on the fly
pointing_matrix, hwp_angle = obs.get_pointings()
This returns two vectors
print(pointing_matrix.shape) # [n_detectors, n_samples, 3]
# θ (colatitude, in radians), φ (longitude, in radians), and ψ (orientation angle, in radians)
print(hwp_angle.shape) # [n_samples]
(144, 111600, 3)
(111600,)
get_pointings() supports three different syntaxes:
Returns the pointing information for all the detectors with “get_pointings(“all”) or get_pointings()”
Returns the pointing information for a list of detectors with something like “get_pointings([0,1])
Returns the pointing information for one detector with something like “get_pointings(0)
# All the detectors are included
pointings, hwp_angle = obs.get_pointings("all")
# This returns ``(N_det, N_samples, 3)`` array
print(pointings.shape)
# Only the first and last detectors are included
pointings, hwp_angle = obs.get_pointings([0, 3])
# This returns ``(2, N_samples, 3)`` array
print(pointings.shape)
# Only the first detector is used
pointings, hwp_angle = obs.get_pointings(0)
# This returns ``(N_samples, 3)`` array
print(pointings.shape)
(144, 111600, 3)
(2, 111600, 3)
(111600, 3)
Pointing information can be precomputed and stored in the observations
sim.precompute_pointings()
Now all the observations have two new fields
print(obs.pointing_matrix.shape)
print(obs.hwp_angle.shape)
(144, 111600, 3)
(111600,)
The pointing type can be explicitly selected by specifying it in either get_pointings() or precompute_pointings()
pointings, hwp_angle = obs.get_pointings(0, pointings_dtype=np.float32)
print(pointings.dtype)
sim.precompute_pointings(pointings_dtype=np.float32)
print(obs.pointing_matrix.dtype)
float32
float32
A method is also provided to convert the pointing of a single detector on the fly into Galactic coordinates.
pointing_gal = lbs.rotate_coordinates_e2g(obs.pointing_matrix[0])
This allows both to scan or convolve a map and to return maps in Galactic coordinates. Rotation is always performed on-the-fly. For example see the signatures for these functions:
print("fill_tods")
print("---------")
sig = inspect.signature(sim.fill_tods)
for param in sig.parameters.values():
print(param)
print("")
print("convolve_sky")
print("---------")
sig = inspect.signature(sim.convolve_sky)
for param in sig.parameters.values():
print(param)
print("")
print("make_binned_map")
print("---------")
sig = inspect.signature(sim.make_binned_map)
for param in sig.parameters.values():
print(param)
fill_tods
---------
maps: litebird_sim.maps_and_harmonics.HealpixMap | dict[str, litebird_sim.maps_and_harmonics.HealpixMap] | litebird_sim.maps_and_harmonics.SphericalHarmonics | dict[str, litebird_sim.maps_and_harmonics.SphericalHarmonics] | None = None
component: str = 'tod'
pointings_dtype=<class 'numpy.float64'>
append_to_report: bool = True
nthreads: int | None = None
convolve_sky
---------
sky_alms: None | litebird_sim.maps_and_harmonics.SphericalHarmonics | dict[str, litebird_sim.maps_and_harmonics.SphericalHarmonics] = None
beam_alms: None | litebird_sim.maps_and_harmonics.SphericalHarmonics | dict[str, litebird_sim.maps_and_harmonics.SphericalHarmonics] = None
input_sky_alms_in_galactic: bool = True
convolution_params: litebird_sim.beam_convolution.BeamConvolutionParameters | None = None
component: str = 'tod'
pointings_dtype=<class 'numpy.float64'>
nside_centering: int | None = None
append_to_report: bool = True
nthreads: int | None = None
make_binned_map
---------
nside: int
output_coordinate_system: litebird_sim.coordinates.CoordinateSystem = <CoordinateSystem.Galactic: 2>
components: str | list[str] = 'tod'
detector_split: str = 'full'
time_split: str = 'full'
pointings_dtype=<class 'numpy.float64'>
append_to_report: bool = True