Observing the CMB

[1]:
import maria
from maria.band import get_band

f090 = get_band("act/pa5/f090")
f150 = get_band("act/pa5/f150")


f090.NET_RJ = 10e-6
f150.NET_RJ = 10e-6

f090.knee = 1e1
f150.knee = 1e1

array = {"field_of_view": 0.7,
         "beam_spacing": 1.5,
         "primary_size": 10,
         "packing": "sunflower",
         "shape": "circle",
         "polarized": True,
         "bands": [f090, f150]}

instrument = maria.get_instrument(array=array)

print(instrument)
instrument.plot()
Instrument(1 array)
├ arrays:
│             n     FOV baseline                        bands polarized
│  array1  1048  41.84’      0 m  [act/pa5/f090,act/pa5/f150]      True
│
└ bands:
              name   center   width    η         NEP      NET_RJ         NET_CMB    FWHM
   0  act/pa5/f090   90 GHz  20 GHz  0.5  1.469 aW√s  10 uK_RJ√s  12.29 uK_CMB√s  1.458’
   1  act/pa5/f150  150 GHz  30 GHz  0.5  2.204 aW√s  10 uK_RJ√s  17.33 uK_CMB√s  52.49”
../_images/tutorials_cmb-patch_1_1.png
[2]:
import numpy as np
from maria import Plan
from maria.plan import *

plan = Plan.generate(duration=600,
                     sample_rate=20,
                     start_time="2026-03-05T12:00:00",
                     scan_center=(45, 45),
                     scan_pattern="back-and-forth",
                     scan_options={"x_throw": 2, "y_throw": 0, "speed": 1e0},
                     frame="az/el",
                     site="cerro_toco")

plan.plot(frames=["az/el", "ra/dec", "glon/glat"])
../_images/tutorials_cmb-patch_2_0.png
[3]:
sim = maria.Simulation(
    instrument=instrument,
    plans=[plan],
    site="cerro_toco",
    cmb="generate",
    cmb_kwargs={"nside": 1024},
)

print(sim)
Generating CMB (nside=1024):   0%|          | 0/1 [00:00<?, ?it/s]2026-06-02 15:40:08.701 INFO: Fetching https://github.com/thomaswmorris/maria-data/raw/master/cmb/spectra/lensed.csv

Downloading: |          | 3.72M/? [00:00<00:00, 101MB/s]
Generating CMB (nside=1024): 100%|██████████| 1/1 [00:09<00:00,  9.75s/it]
Simulation
├ Instrument(1 array)
│ ├ arrays:
│ │             n     FOV baseline                        bands polarized
│ │  array1  1048  41.84’      0 m  [act/pa5/f090,act/pa5/f150]      True
│ │
│ └ bands:
│               name   center   width    η         NEP      NET_RJ         NET_CMB    FWHM
│    0  act/pa5/f090   90 GHz  20 GHz  0.5  1.469 aW√s  10 uK_RJ√s  12.29 uK_CMB√s  1.458’
│    1  act/pa5/f150  150 GHz  30 GHz  0.5  2.204 aW√s  10 uK_RJ√s  17.33 uK_CMB√s  52.49”
├ Site:
│   region: chajnantor
│   timezone: America/Santiago
│   location:
│     longitude: 67°47’16.08” W
│     latitude:  22°57’30.96” S
│     altitude: 5.19 km
│   seasonal: True
│   diurnal: True
├ PlanList(1 plans, 600 s):
│                            start_time duration target(az,el)
│ chunk
│ 0      2026-03-05 12:00:00.000 +00:00    600 s    (45°, 45°)
└ CMB:
    data(3, 1, 1, 12582912):
      min: -5.602e-04
      max: 5.685e-04
      units: K_CMB
      quantity: cmb_temperature_anisotropy
    stokes(3):
      components: ['I' 'Q' 'U']
    nu(1):
      values: [148.] GHz
    z(1):
      values: [1100.]
    pixels(12582912):
      nside: 1024
      resolution: 3.435’
    frame: galactic
    beam(maj, min, rot): (0 rad, 0 rad, 0 rad)
    memory: 302 MB
[4]:
tods = sim.run()
tods[0].plot()
2026-06-02 15:40:17.952 INFO: Simulating observation 1 of 1
Sampling CMB: 100%|██████████| 2/2 [00:02<00:00,  1.20s/it, band=act/pa5/f150, stokes=U]
Generating noise: 100%|██████████| 2/2 [00:01<00:00,  1.43it/s, band=act/pa5/f150]
2026-06-02 15:40:22.371 INFO: Simulated observation 1 of 1 in 4.41 s
../_images/tutorials_cmb-patch_4_1.png
[5]:
from maria.mappers.ml_mapper import *

ml_mapper = MaximumLikelihoodMapper(tods=tods,
                                    frame="ra/dec",
                                    resolution=2 / 60,  # degrees
                                    tod_preprocessing={
                                        "remove_spline": {"knot_spacing": 60, "remove_el_gradient_order": 3},
                                    },
                                    bilinear=False,
                                    k=0)
2026-06-02 15:40:28.011 INFO: Inferring center {'ra': '20ʰ27ᵐ55.64ˢ', 'dec': '10°32’59.91”'} for mapper
2026-06-02 15:40:28.021 INFO: Inferring mapper width 6.322° for mapper from observation patch
2026-06-02 15:40:28.021 INFO: Inferring mapper height 6.322° to match supplied width
2026-06-02 15:40:28.024 INFO: Inferring stokes parameters 'IQU' for mapper from detector sensitivities
Preprocessing TODs: 100%|██████████| 1/1 [00:00<00:00,  1.66it/s]
Computing pointing matrices: 100%|██████████| 1/1 [00:06<00:00,  6.97s/it]
[6]:
print(ml_mapper.map)
ml_mapper.map.plot(slices=dict(stokes=["I", "Q", "U"], nu=[[0], [1]]),
                   cmap="cmb", contrast=1e-4)
ProjectionMap:
  data(3, 2, 189, 189):
    min: -1.624e-04
    max: 1.803e-04
    units: K_RJ
    quantity: rayleigh_jeans_temperature
  stokes(3):
    components: ['I' 'Q' 'U']
  nu(2):
    values: [ 90. 150.] GHz
  eta(189):
    height: 6.267°
    res: -2’
  xi(189):
    width: 6.267°
    res: 2’
  frame: ra/dec
  center:
    ra: 20ʰ27ᵐ55.64ˢ
    dec: 10°32’59.91”
  beam(maj, min, psi): ragged
  memory: 1.715 MB
../_images/tutorials_cmb-patch_6_1.png