E79 CMB sky behind the LMC mask¶
This tutorial does the main part of the pymc-challenges notebook E79_cmb_field_level.py in
the web app. You use the model sci.cmb_field@1. You do not write NumPy or PyMC code.
You need:
- The platform (start it with
make dev) and a project that you can upload datasets to. This tutorial uses the projectastronomy. If your project has a different name, change the project part of eachdataset://andmodel://reference. - A local copy of pymc-challenges. The export command reads two files from its
data/directory. - About 30 minutes. On a laptop, the fit took about 2 minutes.
1. The question¶
The cosmic microwave background (CMB) is the oldest light in the universe. Its temperature changes by about 100 µK from one part of the sky to another. These spots are a Gaussian random field. The power spectrum gives the strength of the spots at each angular scale (multipole ℓ ≈ 180° / angle).
The notebook uses a 16 × 16 degree patch of the Planck 2018 SMICA map. The patch is around the Large Magellanic Cloud (LMC). The dust and the gas of the LMC are brighter than the CMB, so the Planck mask removes a hole of about 4 degrees. The mask also removes some small holes around bright radio sources. In total, 16.5% of the pixels have no data.
The notebook makes each pixel of the sky a parameter (field-level inference). It samples the sky together with the power spectrum in 26 bins (bandpowers). It asks two questions:
- What does the CMB look like behind the LMC, and how sure are we of each pixel? (Notebook part F.)
- Does the visible part of the patch agree with the Planck spectrum? (Notebook parts F and H.)
The notebook ends in this result: the LMC patch agrees with the Planck spectrum. The amplitude of the patch is within 1.4% of Planck (log amplitude −0.014 ± 0.023), and the tilt is −0.009 ± 0.030. Behind the LMC, the posterior mean is not a plausible sky. It is too smooth. Each posterior draw is a plausible sky, and each draw fills the hole differently. Thus show the draws and the sd map, not one "true" sky behind the mask.
What you will get, and the notebook part that each item replaces:
| In the web app | Notebook |
|---|---|
The dataset astronomy/planck_smica_lmc: the map with the mask, a noise map, the Planck spectrum and the pixel window |
Part A: the data, the mask and the noise from the half-mission maps |
| A fit with the Wandelt-Eriksen Gibbs sampler (Runs) | Part E: the Gibbs sampler |
The posterior of the 26 bandpowers, the amplitude and the tilt (Parameters, sci.power_spectrum) |
Part F, "Bandpowers", and part H, the amplitude-and-tilt model |
| Sky maps with mean, sd and draws (Fields) | Part F: the posterior sky, the sd map and the animation |
The observed map next to posterior skies (sci.ppc_image_grid) |
Part F: the posterior mean map and four posterior skies |
log_amplitude, tilt and bandpower_ratio with a 90% range (Score) |
Part H: amplitude and tilt on the real patch |
| Skies of new patches with the same spectrum (Score, mode Simulate) | Part B: "Is the real sky just a random draw?" |
The port does not do parts C (the naive spectrum estimate), D (PyMC and HMC) and G (the coverage on simulated skies). See Differences from the notebook.
2. Get the data¶
The export command reads planck_smica_patches.npz and planck_theory_tt.txt. It writes a
NetCDF file that the platform can read. It prepares the map as the notebook does:
- It averages the 3.75 arcmin pixels to 7.5 arcmin pixels: 128 × 128 pixels.
- A pixel is usable only if all of its samples are inside the Planck common mask. The other pixels get NaN.
- The noise sd of each pixel is the local rms of the half-mission half-difference map, smoothed over 1 degree.
- The reference spectrum is the Planck 2018 best-fit TT spectrum, with the HEALPix pixel window of the source map.
Run the command from the root of the modeling-api repository:
uv run python -m mapi_plugin_science.export e79 \
--challenges <path to pymc-challenges>/data \
--out planck_smica_lmc.nc --spec planck_smica_lmc.yaml
The command writes:
wrote planck_smica_lmc.nc (variables temperature, noise_sd, reference_dl, pixel_window on row=128, col=128, multipole=4097)
upload it as dataset astronomy/planck_smica_lmc and fit sci.cmb_field
wrote the suggested spec to planck_smica_lmc.yaml
The file holds one dataset (about 370 KB):
| Name | Dims | Type | Meaning |
|---|---|---|---|
row, col |
128, 128 | integer, fixed | The pixels of the patch. Row 0 is the bottom row |
multipole |
4097 | integer, fixed, 0 to 4096 | The multipole ℓ of the spectrum |
temperature |
row, col |
float64, µK, target | The SMICA temperature. NaN in 2,703 masked pixels (16.5%) |
noise_sd |
row, col |
float64, µK, weight | The noise sd of each pixel: 1.5 µK to 3.4 µK |
reference_dl |
multipole |
float64, µK², constant | The Planck best-fit spectrum D_ℓ = ℓ(ℓ+1)C_ℓ/2π |
pixel_window |
multipole |
float64, constant | The HEALPix pixel window (Nside 2048) |
The attributes of the file keep the constants of the map: pixel_arcmin 7.5,
beam_fwhm_arcmin 5.0, pixel_subsamples 8, patch lmc and centre_lb_deg (280, −35). The
attribute mapi_schema gives each variable its role, so you do not map columns.
No pymc-challenges copy?
--synthetic writes a simulated patch from the model's own prior: a 32 × 32 map with a
hole, a test spectrum and a known amplitude (1.15) and tilt (−0.1). Use it to try the
steps. The numbers in this tutorial are for the real patch. For the simulated patch, use
the settings of CMB_SPEC_YAML in mapi_plugin_science.cmb_data. With --synthetic,
the --spec file has the bandpower bins of that spec (bin_edges), because the
simulated patch is too small for the first default bin.
3. Upload the dataset¶
- Open Datasets in the sidebar.
- Click New dataset.
- Type
planck_smica_lmcin Name. Type a description, for example "Planck 2018 SMICA patch around the LMC, with the common mask and a noise map". - Click Create dataset. The upload panel opens.
- Click Choose files and select
planck_smica_lmc.nc. - Make sure that the format is netCDF (or HDF5 written by xarray).
- Click Preview structure. The panel shows Structure of the file. Make sure that it
shows
temperatureandnoise_sdonrowandcol, andreference_dlandpixel_windowonmultipole. - Optional: type a message in Version message (optional).
- Click Upload and ingest.
The ingest run reads the file in the sandbox. When it is done, the version page shows the tabs
Schema, Coordinates, Missingness, Preview and About. On Schema, temperature has the role
target, noise_sd the role weight, and reference_dl and pixel_window the role
constant. Missingness shows 2,703 missing values in temperature. These are the masked
pixels. The model does not fill them before the fit: a masked pixel has no data term.
Note
The file has no groups, so the upload makes a flat dataset. Do not open "Put this file in a node of a tree (optional)".
3.1 Explore the data¶
Look at the data before you build the spec.
- On the version page, click Explore this version. The Data Explorer opens. The sections under Pictures of the data come first.
-
Click Images and fields.
-
The viewer shows
temperatureandnoise_sdon a grid of 128 × 128 pixels.temperaturehas values on the two sides of zero, thus its colour map has two colours. - Click Profiles and spectra. The profiles show
reference_dlandpixel_windowalongmultipole(4,097 values). The x axis is logarithmic. - The time sections are in Not for this data.
Refer to Scientific data.
4. Build the spec¶
- Open Build and click New spec. The editor opens with the geo MMM template.
- Set the Editor view to YAML.
- Open the Insert panel on the right.
- Open the Datasets section and select
planck_smica_lmc. The toast "Dataset set" shows. - Type
cmbin the search field. Under Models, select Sky map behind a mask (CMB) (sci.cmb_field@^1). The toast "Model set" shows. - Select all the text in the editor and paste the full spec below. The template has other blocks (a pipeline, a split and the MMM plots), so the spec must replace all of it.
- Click Validate. The status shows
valid. - Click Save spec. The spec gets its name
planck-smica-lmcfrommetadata.name.
This is the full spec:
apiVersion: mapi/v1
kind: ModelSpec
metadata:
name: planck-smica-lmc
project: astronomy
data:
dataset: dataset://astronomy/planck_smica_lmc@latest
model:
use: sci.cmb_field@^1
settings:
pixel_arcmin: 7.5
beam_fwhm_arcmin: 5.0
pixel_subsamples: 8
pixel_window: true
projection: gnomonic
border: 8
field_draws: 40
fit:
mode: train_only
engine: gibbs
seed: 79
tune: 16
draws: 64
chains: 4
outputs:
plots:
- core.convergence
- sci.power_spectrum
- sci.field_map
- sci.image_residuals
- sci.ppc_image_grid
The settings come from the suggested spec of the export (planck_smica_lmc.yaml). This table
tells what each setting means for this patch:
| Setting | Value | Meaning for this question |
|---|---|---|
pixel_arcmin |
7.5 | The side of a map pixel in arcmin. With 128 pixels, the patch is 16 degrees wide |
beam_fwhm_arcmin |
5.0 | The SMICA beam: a Gaussian with a FWHM of 5 arcmin. The model compares the data with the sky as Planck sees it, after the beam |
pixel_subsamples |
8 | Each 7.5 arcmin pixel is the mean of 8 × 8 point samples (a box window) |
pixel_window |
true | Use the variable pixel_window: the HEALPix pixels of the source map also smooth the sky |
projection |
gnomonic |
Correct the multipoles for the mean stretch of the tangent-plane projection (about 1%). flat turns the correction off |
border |
8 | 8 pixels (1 degree) without data on each side. The sky is periodic on a 144 × 144 torus, but the real patch is not periodic. Without the border, the seam makes false small-scale power |
field_draws |
40 | The number of sky maps that each score draws. The notebook animation also uses 40 skies |
These settings keep their defaults, which are the values of the notebook:
bin_edges: the 26 bins of the notebook, from ℓ = 0 to ℓ = 2100.ell_dense: 300: the dense preconditioner of CG for the 681 modes below ℓ = 300.cg_tol: 1e-5: the stop rule of CG. A looser stop rule makes the large-scale bins too low (notebook part G).rescale: true: the non-centred rescaling move. It helps in the bins where the noise is larger than the sky.tilt_pivot: 500andtilt_max_ell: 1450: the pivot of the tilt, and the three top bins that the amplitude-and-tilt summary leaves out (notebook part H).
Notes about the other blocks:
fit.mode: train_onlyfits on all of the pixels. The suggested spec of the export hasevaluate: {metrics: [rmse, mae, coverage_90]}and no split. With that spec, the validator shows the warningSPLIT_INVALID("There is no holdout for the evaluation"). Remove theevaluateblock and addmode: train_only.tune: 16anddraws: 64give 4 chains of 80 Gibbs iterations, as in the notebook. The first 16 iterations of each chain are burn-in.engine: gibbsis the only engine of this model. The model has no NUTS.- The model has no pointwise log likelihood (
loo_validis false), because all of the pixels share one latent sky. Thuselpd_loois not available. Compare two fits by their bandpowers, amplitude and tilt.
The plots
The fit makes only the plots in outputs.plots. The spec keeps all five plots that the
model declares. sci.field_map, sci.image_residuals and sci.ppc_image_grid use the
in-sample sky maps that the run makes after the fit. In the Insert panel, the Plots
section adds a plot for you.
5. Fit and watch the run¶
- Click Fit. The app opens the run page.
- The badge shows Live while the run sends events.
- The Progress card shows "Gibbs iteration N of 80". The Events card shows the stages of the run and, at the end, the diagnostics. The Logs card stays empty when the model writes no output.
- When the run is done, the Result card shows Inspect model://astronomy/planck-smica-lmc@v1. Click it.
All four chains run together. Each Gibbs iteration has three steps:
- A constrained realisation: a draw of the full sky (20,736 pixels on the torus) for the current bandpowers. Preconditioned conjugate gradients (CG) solve one linear system. In our fit, CG took about 370 iterations for each solve.
- A draw of each bandpower from its inverse-gamma distribution, given the sky.
- The rescaling move for each bin. It is almost always rejected in the large-scale bins and accepted about half of the time in the top bins. The notebook found the same.
After the fit, the run calculates the in-sample sky maps, the plots and the explorer views.
You can also find the run under Runs. Filter it with the kind fit.
6. Read the result¶
On the model version page, the tabs are Overview, Diagnostics, Plots, Data tree, Preprocessing and Provenance. Click Explore to open the Model Explorer.
6.1 Can you trust the fit?¶
Open Diagnostics in the Model Explorer (group "Can you trust it?").
With 4 chains of 64 kept draws, expect these results:
| Code | Value | Message |
|---|---|---|
RHAT |
1.10 (error) | "The independent sampler runs do not agree about 'q'. Its estimates are not reliable at this time." |
ESS_BULK |
42 | "There is too little independent information about 'q' (about 42 effective draws). The averages are not stable." |
ESS_TAIL |
59 | The same message for the intervals |
These values agree with the notebook. The notebook reports "r_hat is at most 1.11 and bulk ESS runs from 28 to about 200 out of 256 draws - enough for bandpowers". The worst bins are in the middle of the spectrum (ℓ ≈ 600 and ℓ ≈ 1400). The amplitude and the tilt converge better: R-hat 1.01 and a bulk ESS of about 250.
If the diagnostic CG_NOT_CONVERGED shows, a CG solve stopped at cg_max_iter. Then the
large-scale bandpowers can be too low. Increase cg_max_iter or ell_dense.
A longer fit
The RHAT error comes from the short chains of the notebook, not from a wrong model. Set
tune: 40 and draws: 240 and fit again. On a laptop, this fit took about 4 minutes. It
gave R-hat 1.04 (a warning) and a bulk ESS of 100. The amplitude and the tilt changed by
less than 0.2 posterior sd.
On the model version page, the Plots tab has core.convergence. Its caption names the
parameters that did not converge. The caption uses the limits 1.01 and 400 effective draws,
so with 256 draws it lists all 80 values of q, bandpower and bandpower_ratio.
6.2 What did the model learn?¶
Open Parameters (group "What it learned"). The posterior has these variables:
| Variable | Meaning |
|---|---|
q (bin) |
The log ratio of the bandpower to the Planck reference in each of the 26 bins |
bandpower (bin) |
The bandpower D_ℓ of each bin in µK² |
bandpower_ratio (bin) |
exp(q): the bandpower divided by the reference |
log_amplitude |
The log amplitude of the bandpowers relative to Planck |
tilt |
The tilt of the bandpowers relative to Planck, at ℓ = 500 |
The bin dim has the coords ell (the centre of the bin), ell_low and ell_high.
The main results, with the notebook values:
| Quantity | This fit | Notebook | Meaning |
|---|---|---|---|
log_amplitude |
−0.018 ± 0.022 | −0.014 ± 0.023 | The patch is within 2% of the Planck amplitude |
tilt |
0.001 ± 0.030 | −0.009 ± 0.030 | No tilt relative to Planck |
bandpower_ratio at ℓ ≈ 80 |
1.39 ± 0.33 | 40% high, 25% uncertainty | The largest departure. A 16-degree patch has few large-scale modes (cosmic variance) |
bandpower_ratio at ℓ ≈ 1950 |
1.17 ± 0.12 | 18% high | The top bin |
| Masked fraction | 16.5% | 16.5% (masked_fraction in the learned values) |
The LMC hole and the small holes |
The amplitude and the tilt are the exact Gaussian posterior of the notebook's part H model,
q_b = log A + tilt · log(ℓ_b / 500), with the bins below ℓ = 1450. The fit gives one draw of
them for each Gibbs draw. The learned values also keep log_amplitude_mean,
log_amplitude_sd, tilt_mean and tilt_sd.
On the model version page, open Plots and select sci.power_spectrum. Its caption says
"The line is the median of bandpower in each bin of ell, from 256 draws of posterior. The
shaded bands are the 50% and 90% intervals." The line must follow the acoustic peaks of the
Planck spectrum, with wide bands at small ℓ and narrow bands at large ℓ. The plot does not
draw the Planck reference. To compare with Planck, read bandpower_ratio in Parameters or
score it (step 7.1). Each bin must be near 1.
6.3 The sky behind the LMC (Fields)¶
Open Fields (group "What it learned"). The text says "The model has 2 outputs on a grid." Select the output in Output:
skyis the sky as Planck sees it (after the beam), onrowandcol, in diverging colours. The view uses 40 posterior draws.temperature_hatis the same map. It adds noise only in a predictive score, so here it is equal tosky.
Select sky and do these steps:
- Select Statistic Mean. Outside the mask, the map is the SMICA map. In the LMC hole, the mean continues the spots that cross the edge of the hole for a fraction of a degree. Then it fades to a smooth, almost flat level. The mean is the best single guess, but it is not a plausible sky.
- Select Std. dev. The sd is near the noise level (about 2.5 µK) where there are data. In the LMC hole, it rises to about 90 µK in the middle. That is almost the prior sd of a pixel: the data tell nothing there. The small holes around the radio sources are between, at about 37 µK.
- Select Draws and click Play the draws. This is the animation of the notebook. The pixels that stand still are known. The pixels that flicker are not known. Each draw fills the hole with spots of the correct size and contrast, and each draw is different.
Move the pointer over the map to read the values of one pixel.
The fit also keeps the derived group sky_moments: the mean and the sd of each pixel over all
256 kept Gibbs draws. The Fields view uses the 40 draws of the in-sample score, so its sd
is a little noisier. In our fit, the mean sd over the LMC hole was 80 µK, with a maximum of
108 µK.
On the model version page, open Plots:
| Plot | What to look for |
|---|---|
core.convergence |
R-hat and ESS of the bins (step 6.1) |
sci.power_spectrum |
The bandpowers with their 50% and 90% bands (step 6.2) |
sci.field_map |
The mean and the sd of sky. The sd map shows the LMC hole as a large bright area and the small holes as dots |
sci.image_residuals |
The observed temperature, the mean of sky, the residual and the normalised residual |
sci.ppc_image_grid |
The observed map next to 5 posterior skies on one colour scale. The observed map has an empty hole. Each sky fills the hole differently |
The residual plot of this model
In our fit, the caption of sci.image_residuals says: "The normalised residuals have an
sd of 0.28 and 0% are outside ±2 … Here the residuals are too small: the uncertainty is
too large." For this model, that is not a sign of a bad fit. On this map, the sky is
stronger than the noise at almost all the scales of the grid. Thus each sky draw follows
the data closely, and the residual is small (about 0.7 µK). The sd of the draws is about
the noise level (2.5 µK). The residual plot cannot separate the noise from the sky here.
The notebook does the calibration check with simulated skies (part G), not with the
residuals.
6.4 The decision¶
The decision. The visible part of the patch agrees with the Planck spectrum. Report the
amplitude and the tilt with their posterior sd: −0.018 ± 0.022 and 0.001 ± 0.030 in this fit.
Both are within one sd of zero. No bin is more than about 1.7 sd from Planck (in q).
For the sky behind the LMC, show the posterior draws and the sd map, not the mean alone. The mean is too smooth inside the hole. The draws are plausible skies, but no draw is "the" answer. The sd map shows where the data stop: inside the hole, the map knows almost nothing 1 to 2 degrees from the nearest data.
Remember that one 16-degree patch is 0.6% of the sky. The error bars are large. A systematic error of 1% to 2% (for example the projection correction) is small here, but it would be many sds on the full sky. Do step 10, "Next steps", to measure one of these systematic errors.
7. Score the model¶
Each score draws new sky maps from the posterior. A score needs a dataset. Send the dataset that you fitted. The model uses its grid and its noise map.
7.1 The amplitude, the tilt and the bandpowers¶
- On the model version page, click Score.
- In What do you want to do?, select Predict.
- In Values to score, select Use a dataset.
- Type or select
dataset://astronomy/planck_smica_lmc@latestin Dataset. - Open Advanced. Set Seed (optional) to
79. Typelog_amplitude, tilt, bandpower_ratioin Variables (optional). - Click Predict.
The Results card shows the mean and the 90% interval (hdi_90) of each output.
No new data
The page does not show No new data for this model. The model cannot forecast, so a request without a dataset has no forecast horizon, and the server refuses it. A note under Values to score gives this reason.
This is the request that the page sends (POST /v1/models/{model_id}/versions/{v}:score):
{
"apiVersion": "mapi/v1",
"kind": "ScoreRequest",
"model": "model://astronomy/planck-smica-lmc@latest",
"mode": "predict",
"data": "dataset://astronomy/planck_smica_lmc@latest",
"output": {
"kind": "expected",
"summary": ["mean", "hdi_90"],
"vars": ["log_amplitude", "tilt", "bandpower_ratio"]
},
"seed": 79
}
In our fit, the result was log_amplitude −0.018 (90% interval −0.055 to 0.005) and tilt
0.003 (−0.034 to 0.057). A score uses field_draws (40) posterior draws, not all 256. Thus
its numbers are a little different from the Parameters section.
- To get the sky maps, type
skyin Variables (optional). Each draw is a constrained realisation, so the result is the mean and the 90% interval of each pixel. - To get a part of the map, add
"select": {"row": [60, 61, 62], "col": [60, 61, 62]}. "kind": "predictive"adds white noise withnoise_sdtotemperature_hat. It does not changesky.
7.2 Simulate new patches¶
simulate makes skies of a new patch with the spectrum of each posterior draw, plus noise.
The data do not constrain these skies. The notebook asks the same question in part B: does the
real sky look like a random draw with this spectrum?
- In What do you want to do?, select Simulate.
- In Values to score, select Use a dataset, with the same dataset.
- Open Advanced. Set Quantity to Predictive.
- Type
temperature_hatin Variables (optional). Set Draws to8. - Click Simulate.
{
"apiVersion": "mapi/v1",
"kind": "ScoreRequest",
"model": "model://astronomy/planck-smica-lmc@latest",
"mode": "simulate",
"data": "dataset://astronomy/planck_smica_lmc@latest",
"output": {
"kind": "predictive",
"summary": ["mean", "sd"],
"draws": 8,
"vars": ["temperature_hat"]
},
"seed": 79
}
The result has 8 simulated maps of 128 × 128 pixels. The sd over the maps is about 96 µK in each pixel, the same as the rms of the real map (96 µK). A simulated map has no hole and no LMC. Compare it with the real map outside the mask. It must have spots of the same size and contrast.
If you promote the version to an endpoint, Integrations → the endpoint → Schema and Try it sends the same requests.
8. Run a workflow recipe¶
The recipe sci_image_model_check (Image model check) is for models that predict an
image. It fits the model,
makes the residual maps and the image grid, does a posterior predictive check and writes a
report.
- Set the header to Guided and open Recipes. In Expert mode, open Workflows and then the Templates tab.
- Find the card Image model check and click Run on my data.
- In 1. Your data, select
planck_smica_lmcin Dataset. - In 2. What the recipe needs to know, type
sci.cmb_field@^1in Model. - Open Fine-tune (optional: the defaults are correct for most data). Set these values:
- Settings: the settings of step 4 as JSON:
{"pixel_arcmin": 7.5, "beam_fwhm_arcmin": 5.0, "pixel_subsamples": 8, "pixel_window": true, "projection": "gnomonic", "border": 8, "field_draws": 40}. - Draws
64, Tune16, Chains4and Seed79. - Var:
sky.
- Settings: the settings of step 4 as JSON:
- Click Run this recipe.
Set draws and tune
Set Draws and Tune before you run the recipe. The defaults are 1000 and 1000. For this model, that is 2,000 Gibbs iterations, about 25 times as long as the fit of step 5.
The monitor of the run has the tabs Graph, Steps, Decisions, Outputs and Events. Outputs shows the parameter table, the two plots, the coverage of the 50% and 90% ranges and the report. For this model, expect a coverage near 100% and the same note as in step 6.3. The sky draws follow the data closely, so the in-sample check cannot find a problem with the noise model.
The recipe bayes_workflow_audit (Bayesian workflow audit) does all the checks of a
Bayesian workflow on any model with draws: a convergence gate, the posterior predictive check, sensitivity.prior and
recovery.simulated. Run it in the same way with the model sci.cmb_field@^1 and these
changes:
- Set Prior predictive to
{}. This model does not sample its priors. - Set Draws
240and Tune40. Set Rhat max to1.1and Min ess to50. With the defaults (1.01 and 400), the gate stops the audit for this model, because the Gibbs chains are short (step 6.1). - Set N sims to
5for a first run.
Note
The checks of bayes_workflow_audit that fit the model again (sensitivity.prior and
recovery.simulated) each take as long as one fit or longer. With 5 simulated datasets,
expect the audit to take half an hour or more.
9. The same with the CLI and the Python client¶
mapi use <tenant>/astronomy
mapi datasets upload planck_smica_lmc.nc --name planck_smica_lmc
mapi check planck-smica-lmc.yaml --remote @ # the server's static validation
mapi fit planck-smica-lmc.yaml --remote @ # create or revise the spec, fit, follow
mapi explore model planck-smica-lmc -s params -s diagnostics -s fields
cat > cmb-score.yaml <<'EOF'
apiVersion: mapi/v1
kind: ScoreRequest
model: model://astronomy/planck-smica-lmc@latest
mode: predict
data: dataset://astronomy/planck_smica_lmc@latest
output: {kind: expected, summary: [mean, hdi_90], vars: [log_amplitude, tilt, bandpower_ratio]}
seed: 79
EOF
mapi score cmb-score.yaml --remote @ --model <model id> --version 1 -o cmb.zarr.zip
mapi workflows init sci_image_model_check --name cmb-check
mapi workflows apply cmb-check.yaml -m "E79 image check"
mapi workflows run cmb-check -i data=dataset://astronomy/planck_smica_lmc@latest \
-p model=sci.cmb_field@^1 -p var=sky -p draws=64 -p tune=16 -p seed=79 \
-p 'settings={"pixel_window": true, "projection": "gnomonic", "border": 8}' \
--watch
The CLI has no models command. Take the model id from the run (mapi runs get <run>)
or from Models in the web app.
from mapi_client import Client
api = Client(project="<tenant>/astronomy")
version = api.datasets.upload("planck_smica_lmc.nc", dataset="planck_smica_lmc")
print(version.ref, version.status.value)
with open("planck-smica-lmc.yaml", encoding="utf-8") as fh:
spec_yaml = fh.read()
revision = api.specs.upsert(spec_yaml)
run = api.runs.fit(revision.spec_id, revision.revision)
run = api.runs.wait(run.id, raise_on_failure=True)
model = next(m for m in api.models.list() if m.name == "planck-smica-lmc")
result = api.models.score(
model.id,
model.latest_version,
{
"model": "model://astronomy/planck-smica-lmc@latest",
"mode": "predict",
"data": "dataset://astronomy/planck_smica_lmc@latest",
"output": {"summary": ["mean", "hdi_90"], "vars": ["log_amplitude", "tilt"]},
"seed": 79,
},
)
summary = result.tree["summary"] # an xr.DataTree (needs the `xarray` extra)
print(summary["log_amplitude"].values, summary["tilt"].values)
10. Differences from the notebook¶
The port keeps the data of part A, the Gibbs sampler of part E, the posterior sky and the bandpowers of part F and the amplitude and tilt of part H. It leaves out these parts:
- The Gaussian random field lessons (part B). The port has no plots of the Hartley modes
or of the phases.
simulategives skies with the posterior spectrum instead. - The naive spectrum estimate (part C). The platform has no masked-map estimate to compare with. The notebook shows that such an estimate is biased at high ℓ.
- The PyMC model with NUTS (part D). The centred and non-centred models, and the failure of HMC on a masked map, are not in the port. The model always uses the Gibbs sampler.
- The coverage on simulated skies (part G). The notebook fits 8 simulated skies with a
known, non-Planck spectrum and finds that 83% of the truths are in the 90% intervals. The
platform does not do this check for you. The
recovery.simulatedcheck ofbayes_workflow_audit(step 8) is the nearest replacement. - The amplitude-and-tilt model in PyMC (part H). The port calculates the same posterior
exactly, inside the fit, as
log_amplitudeandtilt. It does not refit it on the 8 simulated skies. - The comparison with the SMICA inpainted map (part F). The dataset does not have the
inpainted map. In the notebook, the inpainted map is within one posterior sd of the mean in
67% of the hole pixels. With
cmb_data.challenges_reference()in Python, our fit gave 66%. - The Planck full-sky bandpowers and the theory curve in the plots.
sci.power_spectrumshows the bandpowers of the patch only. - The north patch. The export reads only the LMC patch. In Python,
cmb_data.from_challenges(path, patch="north")reads the other patch.
Next steps:
- Fit the spec again with
projection: flatand comparelog_amplitude. The notebook finds a change of 1.4% (about 0.6 sd). This is the systematic error of step 6.4. - Fit the north patch. Make the dataset in Python with
patch="north". It has almost no mask and about two times the noise. - Read the model reference for the other science models.
- Read Model Explorer for more about the Fields section.