Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/NASAARSET/PM2.5_AQ_Online_2026/llms.txt

Use this file to discover all available pages before exploring further.

The SatPM V6.GL.03 product provides global, monthly average near-surface PM₂.₅ concentrations derived from satellite aerosol observations using a convolutional neural network (CNN) model. Files are distributed as NetCDF (.nc) through a public AWS S3 bucket, one file per calendar month, and each file contains a single time slice identified by its filename rather than an embedded time coordinate. In the ARSET 2026 case study this product serves as the primary monthly satellite estimate, compared against hourly ground monitor data to evaluate spatial and temporal agreement over central Chile.

Product Homepage

Overview and documentation for the V6.GL.03 global product

Data Access Portal

Browse and manually download SatPM NetCDF files

File naming and URL pattern

Files are stored at a predictable S3 path. For a given year and month the URL follows this pattern:
https://s3.amazonaws.com/satpmdata/V6GL03/FineResolution/GL/Monthly/{YYYY}/V6GL03.CNNPM25.GL.{YYYYMM}-{YYYYMM}.nc
The start and end month tokens in the filename are identical for monthly files (e.g. 202302-202302). The timestamp for each file is parsed from the filename because the NetCDF itself does not embed a time dimension — the helper function F_time_from_SatPM_url (passed as F_time_from_file to F_subset_and_combine) handles this injection.

Key variables

VariableDescription
PM25Raw monthly PM₂.₅ estimate (µg/m³)
PM25_filteredPM25 with negative values masked to NaN
Negative PM₂.₅ values can appear near retrieval edges or in very clean environments. Always apply the > 0 filter before analysis or plotting to avoid artefacts in statistics and colour scales.

Downloading data programmatically

The snippet below iterates over every calendar month between t_start and t_end, skips files already on disk, downloads missing files with urllib, and collects the local paths into l_files_SatPM. It then calls F_subset_and_combine to crop and merge all monthly files into a single xarray.Dataset before applying the quality filter.
import os
import urllib.request
import numpy as np

# --- configuration ---
s_folder_SatPM = '/content/drive/MyDrive/Colab Notebooks/ARSET/PM25_Training_2026/SatPM_Data'
n_lon_min, n_lat_min = -73.75, -38.0
n_lon_max, n_lat_max = -69.75, -32.0
t_start = np.datetime64('2022-12-01 00:00:00')
t_end   = np.datetime64('2023-03-31 23:59:59')

# --- download loop ---
l_files_SatPM = []
for t_month in np.arange(
    t_start.astype('datetime64[M]'),
    t_end.astype('datetime64[M]') + np.timedelta64(1, 'M'),
    np.timedelta64(1, 'M')
):
    s_year  = str(t_month)[0:4]
    s_month = str(t_month)[5:7]
    s_url = (
        f'https://s3.amazonaws.com/satpmdata/V6GL03/FineResolution/GL/Monthly/'
        f'{s_year}/V6GL03.CNNPM25.GL.{s_year}{s_month}-{s_year}{s_month}.nc'
    )
    s_file = s_url.split('/')[-1]
    s_download_path = os.path.join(s_folder_SatPM, s_file)

    if os.path.exists(s_download_path):
        print(f'{s_file} already downloaded.')
    else:
        urllib.request.urlretrieve(s_url, s_download_path)
        print(f'Downloaded {s_url} to {s_folder_SatPM}')

    l_files_SatPM.append(s_download_path)

Plotting

Pass a_data_SatPM['PM25_filtered'] directly to F_plot_map. Because the time dimension spans multiple months the function automatically computes the time-mean before rendering the colour grid:
F_plot_map(
    a_data_plot=a_data_SatPM['PM25_filtered'],
    n_lat_min=n_lat_min,
    n_lat_max=n_lat_max,
    n_lon_min=n_lon_min,
    n_lon_max=n_lon_max,
    Colorbar_Label='PM$_{2.5}$ [µg/m$^{3}$]',
    Plot_Title=f'SatPM\n(Average {t_start} to {t_end})',
    Colorbar_Limits=[0, 40],
)

Using monthly SatPM values in a comparison table

When building a combined monthly comparison DataFrame, look up the nearest SatPM grid cell for each monitor location and month:
f_data_combined_monthly['SatPM'] = np.nan
for i_row in range(len(f_data_combined_monthly)):
    t_month = f_data_combined_monthly.index[i_row][2]
    n_lat   = f_data_combined_monthly.index[i_row][0]
    n_lon   = f_data_combined_monthly.index[i_row][1]
    f_data_combined_monthly.loc[(n_lat, n_lon, t_month), 'SatPM'] = (
        a_data_SatPM
        .sel(lat=n_lat, lon=n_lon, time=t_month, method='nearest')
        ['PM25_filtered']
        .values
    )
Save the merged subset (a_data_SatPM.to_netcdf(...)) immediately after downloading. On subsequent runs, reloading from the cached file is much faster than re-downloading and re-combining the individual monthly files.

Temporal resolution and comparison notes

SatPM V6.GL.03 is a monthly product, so it can only be compared against ground monitors that have been averaged to the same monthly time scale. In the case study, a minimum of 24 × 20 = 480 valid hourly samples is required before a monitor’s monthly average is considered representative. See F_subset_and_combine for details on how the monthly files are merged into a single xarray object.
Each SatPM NetCDF file lacks a time dimension. If you open files directly with xr.open_dataset without injecting a timestamp via F_time_from_file, the resulting dataset will have no time coordinate and xr.concat will fail. Always pass F_time_from_SatPM_url as the F_time_from_file argument to F_subset_and_combine.

Build docs developers (and LLMs) love