A checklist, a preflight check and the failures met in chapters 1 to 6
Chapters 1 to 6 worked through one forecast question. Your question will differ in region, season, observations or models. This chapter gathers what has to change, and the problems that actually occurred along the way, into a checklist and a small preflight checker you can run on your own inputs before fitting anything.
Every problem below happened in this tutorial with PyCPT 2.10.4, cptio 1.4.0 and CPT 17.8.3. The examples use this tutorial’s real files.
NoteWhat you need to run this page
The full PyCPT environment and the case folder from chapters 1 to 6. One cell asks the Data Library for a forecast that does not exist, to show what PyCPT does then; that needs internet access.
1. The workflow on one page
Step
PyCPT call
Chapter
What went wrong or needed care here
Describe the question
download_args, cpt_args
1
Cross-year seasons shift initialization years
Make the case folder
setup
1
Folder name uses signed numbers; files are named by dataset only
Get the data
download_data, summarize_available_years
2, 6
Units label mm/day on seasonal totals; models missing years or forecasts
Use your own observations
local_predictand_file
3
cptio needs units and missing; no S coordinate
Calibrate
evaluate_models
4
Probability scores are in-sample; plots need PRCP in the name
Read probabilities
construct_flex_fcst
5
Not identical to CPT’s native probabilities
Combine models
construct_mme
6
Equal-weight mean; probability scores stay in-sample
2. Set up this case and record its question
The checker is in the tutorial’s pycpt_tutorial/checks.py. Its first job addresses chapter 1’s quiet failure: PyCPT names downloaded files by dataset only, so a case folder reused for a different question silently reuses the old data. remember_question writes the question into the case folder, and check_question compares a new question with it.
from pathlib import Pathimport datetime as dtimport sysimport tempfileimport pandas as pdimport xarray as xrimport cptdl as dlimport pycptrepo =next((p for p in (Path.cwd(), *Path.cwd().parents) if (p /"pycpt_tutorial").is_dir()), None)sys.path.insert(0, str(repo))from pycpt_tutorial import checkspd.set_option("display.max_colwidth", 160)download_args = {"fdate": dt.datetime(2023, 9, 1),"target": "Oct-Dec","target_first_year": 1991,"target_final_year": 2020,"predictor_extent": {"west": 85, "east": 155, "south": -20, "north": 20},"predictand_extent": {"west": 94, "east": 142, "south": -12, "north": 7},}case_dir = Path.home() /"PyCPT"/"indonesia-ond-2023-sep-init"domain_dir = pycpt.setup(case_dir, download_args["predictor_extent"])local_predictand_file = domain_dir /"data"/"local-CHIRPS3-OND-1991-2020.nc"checks.remember_question(download_args, domain_dir)print(checks.check_question(download_args, domain_dir))new_question =dict(download_args, fdate=dt.datetime(2023, 11, 1), target="Dec-Feb")print(checks.check_question(new_question, domain_dir))
Input data will be saved in ~/PyCPT/indonesia-ond-2023-sep-init/85W-155E_to_-20S-20N/data
Figures will be saved in ~/PyCPT/indonesia-ond-2023-sep-init/85W-155E_to_-20S-20N/figures
Output will be saved in ~/PyCPT/indonesia-ond-2023-sep-init/85W-155E_to_-20S-20N/output
{'check': 'case folder question', 'status': 'ok', 'detail': 'download_args match the question stored in this folder.', 'chapter': 1}
{'check': 'case folder question', 'status': 'fail', 'detail': "This folder's files were downloaded for a different question (changed: fdate, target). Use a new case folder or force_download=True.", 'chapter': 1}
3. Run the preflight check on this case
The check looks only at the inputs: the observations, each model’s hindcasts and forecast, and the question. It fits nothing. Here it runs on two of chapter 6’s ensemble members.
download_args match the question stored in this folder.
1
1
predictand attributes
ok
units='mm', missing=np.float64(-999.0)
3
2
predictand coordinates
ok
['T', 'Tf', 'Ti', 'X', 'Y']
3
3
predictand has no initialization date
ok
no 'S' coordinate
4
4
predictand coverage
ok
3240 locations complete in every season; 0 locations missing some seasons (not tested in this tutorial).
3
5
predictand name
ok
CHIRPS3.PRCP
4
6
observation years
ok
1991-2020 all present
2
7
CFSv2.PRCP: hindcast years
ok
all training years present
2
8
CFSv2.PRCP: dates match observations
ok
hindcast T equals observation T
3
9
CFSv2.PRCP: forecast
ok
initialized 2023-09-01 (expected 2023-09-01)
2
10
CFSv2.PRCP: units label
warn
units attribute is 'mm/day', a rate; the catalog requests examined in chapter 1 multiply by the season length, so confirm whether the values are rates or se...
2
11
SEAS51c.PRCP: hindcast years
ok
all training years present
2
12
SEAS51c.PRCP: dates match observations
ok
hindcast T equals observation T
3
13
SEAS51c.PRCP: forecast
ok
initialized 2023-09-01 (expected 2023-09-01)
2
Nothing fails. The warnings are the units labels from chapter 2: the files say mm/day but hold seasonal totals, which chapter 2 confirmed for CFSv2 by recalculation. For a model you have not checked, treat the warning as a task.
4. The same check on real problem inputs
A model that does not cover the question
Chapter 6’s availability check found that Météo-France System 9 lacks the 1991 and 1992 September starts and has no September 2023 forecast. Ask PyCPT for it anyway:
names = ["METEOFRANCE9.PRCP"]_, mf_hindcasts, mf_forecasts = pycpt.download_data("CHIRPS3.PRCP", local_predictand_file, names, download_args, domain_dir, False)print("Forecast returned by download_data:", mf_forecasts[0])checks.check_case(download_args, "CHIRPS3.PRCP", Y, mf_hindcasts, mf_forecasts, names).query("status != 'ok'")
Downloading METEOFRANCE9.PRCP_f2023
URL: https://iridl.ldeo.columbia.edu/SOURCES/.EU/.Copernicus/.CDS/.C3S/.Meteo_France/.System9/.forecast/.prcp/S/%280000%201%20Sep%202023%29/VALUES/L/1.5/3.5/RANGEEDGES/%5BL%5D//keepgrids/average/Y/-20/20/RANGEEDGES/X/85/155/RANGEEDGES/%5BM%5D/average/c%3A/1000/(mm%20m-1)/%3Ac/mul/c%3A/86400/(s%20day-1)/%3Ac/mul/c%3A/92//units/(days)/def/%3Ac/mul/-999/setmissing_value/%5BX/Y%5D%5BL/S/add%5D/cptv10.tsv
Not found. Continuing without it.
Using local observed predictand dataset
Reusing already-downloaded METEOFRANCE9.PRCP
Forecast returned by download_data: None
check
status
detail
chapter
6
METEOFRANCE9.PRCP: hindcast years
fail
missing target years: [1991, 1992]
2
7
METEOFRANCE9.PRCP: dates match observations
fail
hindcast and observation T differ
3
8
METEOFRANCE9.PRCP: forecast
fail
no forecast for this initialization
6
PyCPT prints “Not found. Continuing without it.” and returns None for the forecast, and the hindcasts arrive without the 1991 and 1992 seasons. PyCPT’s own summarize_available_years warns in this case that “missing hindcasts will be replaced with the missing model’s climatology”, and construct_mme fills a missing forecast with climatology (chapter 6). The check makes both visible before that happens.
Observations that cptio or CPT will reject
The observation file of the Fit & diagnose case was built with the model’s initialization date S attached. That case worked only because it wrapped CPT’s output reader (pycpt_tutorial/cpt_dates.py). The check flags it, together with a missing missing attribute and a name without PRCP, all problems met in chapters 3 and 4:
case_two = xr.open_dataset(repo /"docs/data/fitting-2023/OND-Y.nc").precipitation.load()print("Coordinates of the Fit & diagnose observations:", sorted(case_two.coords))pd.DataFrame(checks.check_predictand(case_two, "CHIRPS3.PRCP")).query("status != 'ok'")
Coordinates of the Fit & diagnose observations: ['S', 'T', 'Tf', 'Ti', 'X', 'Y']
check
status
detail
chapter
2
predictand has no initialization date
fail
Observations carry an 'S' coordinate. With CPT 17.8.3 and cptio 1.4.0 the fit then fails reading CPT output ('Timestamp missing T'). Drop S from the observa...
4
no_missing = Y.copy()no_missing.attrs = {k: v for k, v in Y.attrs.items() if k !="missing"}pd.DataFrame(checks.check_predictand(no_missing, "CHIRPS3 (local)")).query("status != 'ok'")
check
status
detail
chapter
0
predictand attributes
fail
cptio needs a 'units' attribute and a numeric 'missing' attribute; found units='mm', missing=None.
3
4
predictand name
warn
'CHIRPS3 (local)' lacks 'PRCP'; plot_forecasts in PyCPT 2.10.4 then fails (UnboundLocalError). Rainfall names should contain PRCP.
4
5. A checklist for your own case
Work down the list before the first fit, and again whenever the question changes.
The question. Write download_args for your initialization month, target season and training target years. Check the leads and initialization years PyCPT will request (exercise 1 below shows how).
The folder. Use one case folder per question. Call remember_question after the first download and check_question before reusing the folder.
The domains. Map both boxes (chapter 1). Read the folder name’s numbers, not its letters.
The models. Download every candidate and keep those with all training years and the forecast you need, by a rule set before looking at skill (chapter 6).
The observations. Catalog or local. A local file needs units, a numeric missing attribute, T, Ti, Tf, Y, X and no S (chapter 3).
The values. Compare units labels with the numbers (chapter 2). Map the fields once (chapter 2).
The settings. Fixed mode counts as here, or ranges for CPT to choose from. State which, and do not change them after looking at results.
The reading. Cross-validated deterministic skill is the fair comparison; probability scores from evaluate_models and construct_mme are in-sample (chapters 4 to 6). Say which probability method a map uses (chapter 5).
6. Exercises
The answers are computed by PyCPT’s own functions in the cells under each exercise. Try each one before running its cell.
Exercise 1. A June-August forecast is issued on 1 May, and a December-February forecast on 1 November. For training target years 1991-2020, which leads and which initialization years does PyCPT request in each case?
For December-February issued in November, the initialization years run one year earlier than the target years, because a season’s year is the year of its midpoint (chapter 1, step 4).
Exercise 2. You narrow the model domain to 90°E-150°E and 15°S-15°N. What folder does setup create, and does it share files with this chapter’s folder?
Input data will be saved in /tmp/tmp0263lai5/my-case/90W-150E_to_-15S-15N/data
Figures will be saved in /tmp/tmp0263lai5/my-case/90W-150E_to_-15S-15N/figures
Output will be saved in /tmp/tmp0263lai5/my-case/90W-150E_to_-15S-15N/output
New domain folder: 90W-150E_to_-15S-15N
This chapter's domain folder: 85W-155E_to_-20S-20N
Different folders, so no files are shared. Because setup is given the predictor box, as in the template, changing only the predictand box keeps the same folder; then the stored question and check_question are what catch the change.
Exercise 3. Which rainfall observation datasets does the catalog offer, and what is each one? The catalog name is short; the Data Library path in its URL template says more.
for name in dl.observations:if name.endswith(".PRCP"): address = dl.observations[name].split("//", 1)[1]print(f"{name:24s}{address[:95]}")
For Indonesia this tutorial used UCSB.PRCP, whose path names CHIRPS v2.0 (chapter 1). Whether any entry suits your region is a question about the product itself: its coverage, period and method, which the catalog cannot answer.
Exercise 4. Run checks.check_case on your own case, fix every fail, and decide for every warn whether it applies. There is no answer cell: the inputs are yours.
What you have now
One table linking each PyCPT step to the problem it can hide.
A preflight checker, pycpt_tutorial.checks, tested on this tutorial’s real files, that catches every input problem met in chapters 1 to 6.
A checklist and exercises for moving the workflow to your own question.
This is the last Learn PyCPT chapter. The case studies apply the same workflow at a larger scale, across twelve seasons and four years.
IRI Data Library. UCSB CHIRPS version 2.0. https://iridl.ldeo.columbia.edu/SOURCES/.UCSB/.CHIRPS/.v2p0/ Browsing Data Library pages requires signing in (checked 10 November 2026); PyCPT’s data requests in this tutorial succeeded without a key.
Funk, C., Peterson, P., Landsfeld, M., et al. (2015). The climate hazards infrared precipitation with stations: a new environmental record for monitoring extremes. Scientific Data, 2, 150066. https://doi.org/10.1038/sdata.2015.66
Climate Hazards Center, UC Santa Barbara. CHIRPS: Rainfall Estimates from Rain Gauge and Satellite Observations (CHIRPS version 3.0 page). https://www.chc.ucsb.edu/data/chirps3
Funk, C., Peterson, P., Landsfeld, M., et al. (2014). A quasi-global precipitation time series for drought monitoring. U.S. Geological Survey Data Series 832. https://doi.org/10.3133/ds832