PACE Level 2
The Plankton, Aerosol, Cloud, ocean Ecosystem (PACE) Level-2 products provide geolocated (lat/lon) swath data. Each granule contains high-resolution measurements (∼1 km) organized in a two-dimensional swath (scan line × pixel), rather than a regular grid. These data include hyperspectral remote sensing reflectance (Rrs) across hundreds of wavelengths, along with derived products such as chlorophyll-a, inherent optical properties, and atmospheric parameters. We use the PACE_OCI_L2_AOP product for this demonstration.
Steps:
Create a plan for files to use pc.plan()
Print the plan to check it print(plan.summary())
Do the plan and get matchups pc.matchup(plan)
Note: In a virtual machine in AWS us-west-2, where NASA cloud data is, the point matchups are fast. In Colab, say, your compute is not in the same data region nor provider, and the same matchups might take 10x longer.
Prerequisites
The examples here use NASA EarthData and you need to have an account with EarthData. Make sure you can login.
# if needed
! pip install point - collocation
import earthaccess
earthaccess . login ()
<earthaccess.auth.Auth at 0x7fd752432d20>
Here are the level 2 datasets
import earthaccess
results = earthaccess . search_datasets ( instrument = "oci" )
short_names = [
item . summary ()[ "short-name" ]
for item in results
if "L2" in item . summary ()[ "short-name" ]
]
print ( short_names )
['PACE_OCI_L2_UVAI_UAA_NRT', 'PACE_OCI_L2_UVAI_UAA', 'PACE_OCI_L2_AER_UAA_NRT', 'PACE_OCI_L2_AER_UAA', 'PACE_OCI_L2_AOP_NRT', 'PACE_OCI_L2_AOP', 'PACE_OCI_L2_CLOUD_MASK_NRT', 'PACE_OCI_L2_CLOUD_MASK', 'PACE_OCI_L2_CLOUD_NRT', 'PACE_OCI_L2_CLOUD', 'PACE_OCI_L2_LANDVI_NRT', 'PACE_OCI_L2_LANDVI', 'PACE_OCI_L2_BGC_NRT', 'PACE_OCI_L2_BGC', 'PACE_OCI_L2_IOP_NRT', 'PACE_OCI_L2_IOP', 'PACE_OCI_L2_PAR_NRT', 'PACE_OCI_L2_PAR', 'PACE_OCI_L2_SFREFL_NRT', 'PACE_OCI_L2_SFREFL', 'PACE_OCI_L2_TRGAS_NRT', 'PACE_OCI_L2_TRGAS']
Load some points
import pandas as pd
url = (
"https://raw.githubusercontent.com/"
"fish-pace/point-collocation/main/"
"examples/fixtures/points.csv"
)
df_points = pd . read_csv ( url )
print ( len ( df_points ))
df_points . head ()
lat
lon
date
0
27.3835
-82.7375
2024-06-13
1
27.1190
-82.7125
2024-06-14
2
26.9435
-82.8170
2024-06-14
3
26.6875
-82.8065
2024-06-14
4
26.6675
-82.6455
2024-06-14
Get a plan for matchups for 1st 50 points from PACE data
A time buffer is needed since the swath granules are short time windows. We set time_buffer="12h" to find granules that are within 12 hours of our point times.
%% time
import point_collocation as pc
plan = pc . plan (
df_points [ 0 : 50 ],
data_source = "earthaccess" ,
source_kwargs = {
"short_name" : "PACE_OCI_L2_AOP" ,
},
time_buffer = "12h"
)
CPU times: user 21.1 ms, sys: 8.6 ms, total: 29.7 ms
Wall time: 510 ms
Plan: 50 points → 13 unique granule(s)
Points with 0 matches : 0
Points with >1 matches: 10
Time buffer: 0 days 12:00:00
First 5 point(s):
[0] lat=27.3835, lon=-82.7375, time=2024-06-13 12:00:00: 2 match(es)
→ https://obdaac-tea.earthdatacloud.nasa.gov/ob-cumulus-prod-public/PACE_OCI.20240613T171620.L2.OC_AOP.V3_1.nc
→ https://obdaac-tea.earthdatacloud.nasa.gov/ob-cumulus-prod-public/PACE_OCI.20240613T184939.L2.OC_AOP.V3_1.nc
[1] lat=27.1190, lon=-82.7125, time=2024-06-14 12:00:00: 1 match(es)
→ https://obdaac-tea.earthdatacloud.nasa.gov/ob-cumulus-prod-public/PACE_OCI.20240614T175104.L2.OC_AOP.V3_1.nc
[2] lat=26.9435, lon=-82.8170, time=2024-06-14 12:00:00: 1 match(es)
→ https://obdaac-tea.earthdatacloud.nasa.gov/ob-cumulus-prod-public/PACE_OCI.20240614T175104.L2.OC_AOP.V3_1.nc
[3] lat=26.6875, lon=-82.8065, time=2024-06-14 12:00:00: 1 match(es)
→ https://obdaac-tea.earthdatacloud.nasa.gov/ob-cumulus-prod-public/PACE_OCI.20240614T175104.L2.OC_AOP.V3_1.nc
[4] lat=26.6675, lon=-82.6455, time=2024-06-14 12:00:00: 1 match(es)
→ https://obdaac-tea.earthdatacloud.nasa.gov/ob-cumulus-prod-public/PACE_OCI.20240614T175104.L2.OC_AOP.V3_1.nc
Look at the granule to see groups
We will use plan.open_dataset(0) to open the first granule and take a look. This uses open_method="auto". It will try xr.open_dataset, discover no lat/lon and then try xr.open_datatree. You will need to specify what groups to merge. Looking at the datatree, we see want these two groups: /geophysical_data and /navigation_data. We will create a open method dictionary.
%% time
plan . open_dataset ( 0 , open_method = "datatree" )
open_method: {'xarray_open': 'datatree', 'open_kwargs': {'chunks': {}, 'engine': 'h5netcdf', 'decode_timedelta': False}, 'merge': None, 'coords': 'auto', 'set_coords': True, 'dim_renames': None, 'auto_align_phony_dims': None}
CPU times: user 276 ms, sys: 61.8 ms, total: 338 ms
Wall time: 853 ms
<xarray.DataTree>
Group: /
│ Attributes: (12/47)
│ title: OCI Level-2 Data AOP
│ product_name: PACE_OCI.20240613T171120.L2.OC_AOP.V3_...
│ processing_version: 3.1
│ history: l2gen par=/data18/sdpsoper/vdc/vpu37/w...
│ instrument: OCI
│ platform: PACE
│ ... ...
│ geospatial_lon_min: -82.05421
│ startDirection: Ascending
│ endDirection: Ascending
│ day_night_flag: Day
│ earth_sun_distance_correction: 0.9694168567657471
│ geospatial_bounds: POLYGON ((-55.18162 31.32767, -82.0542...
├── Group: /sensor_band_parameters
│ Dimensions: (number_of_bands: 286, number_of_reflective_bands: 286,
│ wavelength_3d: 172)
│ Coordinates:
│ * wavelength_3d (wavelength_3d) float64 1kB 346.0 348.0 351.0 ... 717.0 719.0
│ Dimensions without coordinates: number_of_bands, number_of_reflective_bands
│ Data variables:
│ wavelength (number_of_bands) float64 2kB dask.array<chunksize=(32,), meta=np.ndarray>
│ vcal_gain (number_of_reflective_bands) float32 1kB dask.array<chunksize=(32,), meta=np.ndarray>
│ vcal_offset (number_of_reflective_bands) float32 1kB dask.array<chunksize=(32,), meta=np.ndarray>
│ F0 (number_of_reflective_bands) float32 1kB dask.array<chunksize=(32,), meta=np.ndarray>
│ aw (number_of_reflective_bands) float32 1kB dask.array<chunksize=(32,), meta=np.ndarray>
│ bbw (number_of_reflective_bands) float32 1kB dask.array<chunksize=(32,), meta=np.ndarray>
│ k_oz (number_of_reflective_bands) float32 1kB dask.array<chunksize=(32,), meta=np.ndarray>
│ k_no2 (number_of_reflective_bands) float32 1kB dask.array<chunksize=(32,), meta=np.ndarray>
│ Tau_r (number_of_reflective_bands) float32 1kB dask.array<chunksize=(32,), meta=np.ndarray>
├── Group: /scan_line_attributes
│ Dimensions: (number_of_lines: 1710)
│ Dimensions without coordinates: number_of_lines
│ Data variables: (12/13)
│ year (number_of_lines) float64 14kB dask.array<chunksize=(32,), meta=np.ndarray>
│ day (number_of_lines) float64 14kB dask.array<chunksize=(32,), meta=np.ndarray>
│ msec (number_of_lines) float64 14kB dask.array<chunksize=(32,), meta=np.ndarray>
│ time (number_of_lines) datetime64[ns] 14kB dask.array<chunksize=(32,), meta=np.ndarray>
│ detnum (number_of_lines) float32 7kB dask.array<chunksize=(32,), meta=np.ndarray>
│ mside (number_of_lines) float32 7kB dask.array<chunksize=(32,), meta=np.ndarray>
│ ... ...
│ clon (number_of_lines) float32 7kB dask.array<chunksize=(32,), meta=np.ndarray>
│ elon (number_of_lines) float32 7kB dask.array<chunksize=(32,), meta=np.ndarray>
│ slat (number_of_lines) float32 7kB dask.array<chunksize=(32,), meta=np.ndarray>
│ clat (number_of_lines) float32 7kB dask.array<chunksize=(32,), meta=np.ndarray>
│ elat (number_of_lines) float32 7kB dask.array<chunksize=(32,), meta=np.ndarray>
│ csol_z (number_of_lines) float32 7kB dask.array<chunksize=(32,), meta=np.ndarray>
├── Group: /geophysical_data
│ Dimensions: (number_of_lines: 1710, pixels_per_line: 1272, wavelength_3d: 172)
│ Dimensions without coordinates: number_of_lines, pixels_per_line, wavelength_3d
│ Data variables:
│ Rrs (number_of_lines, pixels_per_line, wavelength_3d) float32 1GB dask.array<chunksize=(32, 256, 40), meta=np.ndarray>
│ Rrs_unc (number_of_lines, pixels_per_line, wavelength_3d) float32 1GB dask.array<chunksize=(32, 256, 40), meta=np.ndarray>
│ aot_865 (number_of_lines, pixels_per_line) float32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
│ angstrom (number_of_lines, pixels_per_line) float32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
│ avw (number_of_lines, pixels_per_line) float32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
│ nflh (number_of_lines, pixels_per_line) float32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
│ l2_flags (number_of_lines, pixels_per_line) int32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
├── Group: /navigation_data
│ Dimensions: (number_of_lines: 1710, pixels_per_line: 1272)
│ Dimensions without coordinates: number_of_lines, pixels_per_line
│ Data variables:
│ longitude (number_of_lines, pixels_per_line) float32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
│ latitude (number_of_lines, pixels_per_line) float32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
│ tilt (number_of_lines) float32 7kB dask.array<chunksize=(32,), meta=np.ndarray>
│ Attributes:
│ gringpointlongitude: [-75.3737 -51.710373 -54.89105 -55.18162 -82.05...
│ gringpointlatitude: [ 3.1425157 8.132527 28.826893 31.327667 25.995...
│ gringpointsequence: [1 2 3 4 5 6]
└── Group: /processing_control
│ Attributes:
│ software_name: l2gen
│ software_version: 9.11.0-09b1279b9
│ input_sources: PACE_OCI.20240613T171120.L1B.V3.nc,oci_gas_transmittan...
│ calibration_data: oci_gains_v3.1_20250722.nc
│ mask_names: ATMFAIL,LAND,CLDICE,HILT
├── Group: /processing_control/input_parameters
│ Attributes: (12/256)
│ ifile: PACE_OCI.20240613T171120.L1B.V3.nc
│ ofile: PACE_OCI.20240613T171120.L2.OC_AOP.V3_1.nc
│ l2prod: Rrs Rrs_unc aot_865 angstrom avw nflh
│ oformat: netCDF4
│ oformat_depth: 8bit
│ fqfile: $OCDATAROOT/common/morel_fq_hyperspectral.nc
│ ... ...
│ spixl: 1
│ epixl: -1
│ dpixl: 1
│ sline: 1
│ eline: -1
│ dline: 1
└── Group: /processing_control/flag_percentages
Attributes: (12/28)
ATMFAIL: 0.023676855
LAND: 21.685057
PRODWARN: 6.5449724
HIGLINT: 8.993618
HILT: 1.804636
HISATZEN: 13.917301
... ...
SEAICE: 0.0
NAVFAIL: 0.0
FILTER: 0.0
BOWTIEDEL: 0.0
HIPOL: 0.037285298
PRODFAIL: 86.22021
/sensor_band_parameters(10) Dimensions: number_of_bands : 286number_of_reflective_bands : 286wavelength_3d : 172Coordinates: (1)
Data variables: (9)
wavelength
(number_of_bands)
float64
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : wavelengths units : nm valid_min : 0 valid_max : 20000 Array Chunk Bytes 2.23 kiB 256 B Shape (286,) (32,) Dask graph 9 chunks in 2 graph layers Data type float64 numpy.ndarray
286 1
vcal_gain
(number_of_reflective_bands)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Vicarious Calibration Gain valid_min : 0.0 valid_max : 2.0 Array Chunk Bytes 1.12 kiB 128 B Shape (286,) (32,) Dask graph 9 chunks in 2 graph layers Data type float32 numpy.ndarray
286 1
vcal_offset
(number_of_reflective_bands)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Vicarious Calibration Offset units : mW cm^-2 um^-1 sr^-1 valid_min : 0.0 valid_max : 10.0 Array Chunk Bytes 1.12 kiB 128 B Shape (286,) (32,) Dask graph 9 chunks in 2 graph layers Data type float32 numpy.ndarray
286 1
F0
(number_of_reflective_bands)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Mean Solar Flux units : W m^-2 um^-1 valid_min : 0.0 valid_max : 2500.0 Array Chunk Bytes 1.12 kiB 128 B Shape (286,) (32,) Dask graph 9 chunks in 2 graph layers Data type float32 numpy.ndarray
286 1
aw
(number_of_reflective_bands)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Band-pass averaged absorption coefficient for seawater units : m^-1 standard_name : volume_absorption_coefficient_of_radiative_flux_in_sea_water valid_min : 1e-04 valid_max : 5.0 reference : Pope, R.M. and Fry, E.S., 1997, "Absorption spectrum (380-700 nm) of pure water. II. Integrating cavity measurements," Appl. Opt.,36, 8710-8723.; Kou, L., Labrie, D., Chylek, P., 1993, "Refractive indices of water and ice in the 0.65-2.5 m spectral range," Appl. Opt.,32, 3531-3540 (1993). Array Chunk Bytes 1.12 kiB 128 B Shape (286,) (32,) Dask graph 9 chunks in 2 graph layers Data type float32 numpy.ndarray
286 1
bbw
(number_of_reflective_bands)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Band-pass averaged backscattering coefficient for seawater units : m^-1 standard_name : volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water valid_min : 5e-06 valid_max : 1.0 reference : Zhang, X., Hu, L., and He, M.-X. (2009). Scattering by pure seawater: effect of salinity, Opt. Express 17(7) comment : These are nominal values for a salinity of 38.4 at 20 degrees C. The bbw values used in the processing are corrected for temperature and salinity on a per pixel basis. Array Chunk Bytes 1.12 kiB 128 B Shape (286,) (32,) Dask graph 9 chunks in 2 graph layers Data type float32 numpy.ndarray
286 1
k_oz
(number_of_reflective_bands)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Ozone Absorption cross-sections units : cm^-1 valid_min : 0.0 valid_max : 0.1 reference : Anderson, S.M., Morton, J., and Mauersberger, K. "Near-infrared absorption spectra of 16O3 and 18O3: Adiabatic energy of the 1A2 state?." The Journal of Chemical Physics 93.6 (1990): 3826-3832.; Anderson, Stuart M., Maeder, J., and Mauersberger, K. "Effect of isotopic substitution on the visible absorption spectrum of ozone." The Journal of chemical physics 94.10 (1991): 6351-6357; http://dx.doi.org/10.1029/92GL00780; http://dx.doi.org/10.1029/93GL01765; http://dx.doi.org/10.1029/93GL02311 comment : Computed at 229.15K with code provided by E.P.Shettle, NRL, Washington, DC; Based on the measurements of: S.Anderson et al. and J. Burkholder and Talukdar (1994) Array Chunk Bytes 1.12 kiB 128 B Shape (286,) (32,) Dask graph 9 chunks in 2 graph layers Data type float32 numpy.ndarray
286 1
k_no2
(number_of_reflective_bands)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : NO2 Absorption cross-sections units : cm^2 molecule^-1 valid_min : 0.0 valid_max : 0.1 reference : K. Bogumil, et al., "Measurements of molecular absorption spectra with the SCIAMACHY pre-flight model: Instrument characterization and reference data for atmospheric remote sensing in the 230-2380 nm region," J. Photochem. Photobiol. A.: Photochem. 157, 167-184 (2003).; W. Schneider,et al., "Absorption cross-sections of NO2 in the UV and visible region (200 - 700 nm) at 298 K", J. Photochem. Photobiol. 40, 195-217 (1987) Array Chunk Bytes 1.12 kiB 128 B Shape (286,) (32,) Dask graph 9 chunks in 2 graph layers Data type float32 numpy.ndarray
286 1
Tau_r
(number_of_reflective_bands)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Rayleigh Optical Thickness valid_min : 0.0 valid_max : 0.5 reference : Bodhaine, B.A., Wood, N.B, Dutton, E.G., Slusser, J.R. (1999). On Rayleigh Optical Depth Calculations, J. Atmos. Ocean Tech., 16, 1854-1861. Array Chunk Bytes 1.12 kiB 128 B Shape (286,) (32,) Dask graph 9 chunks in 2 graph layers Data type float32 numpy.ndarray
286 1
/scan_line_attributes(13) Dimensions: Data variables: (13)
year
(number_of_lines)
float64
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Scan year units : years valid_min : 1900 valid_max : 2100 Array Chunk Bytes 13.36 kiB 256 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float64 numpy.ndarray
1710 1
day
(number_of_lines)
float64
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Scan day of year units : days valid_min : 0 valid_max : 366 Array Chunk Bytes 13.36 kiB 256 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float64 numpy.ndarray
1710 1
msec
(number_of_lines)
float64
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Scan time, milliseconds of day units : milliseconds valid_min : 0 valid_max : 86400000 Array Chunk Bytes 13.36 kiB 256 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float64 numpy.ndarray
1710 1
time
(number_of_lines)
datetime64[ns]
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : scan line time in seconds since 1970-1-1 Array Chunk Bytes 13.36 kiB 256 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type datetime64[ns] numpy.ndarray
1710 1
detnum
(number_of_lines)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Detector Number (zero-based) valid_min : 0 valid_max : 25 Array Chunk Bytes 6.68 kiB 128 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float32 numpy.ndarray
1710 1
mside
(number_of_lines)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Mirror Side (zero-based) valid_min : 0 valid_max : 1 Array Chunk Bytes 6.68 kiB 128 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float32 numpy.ndarray
1710 1
slon
(number_of_lines)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Starting Longitude units : degrees_east standard_name : longitude valid_min : -180.0 valid_max : 180.0 Array Chunk Bytes 6.68 kiB 128 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float32 numpy.ndarray
1710 1
clon
(number_of_lines)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Center Longitude units : degrees_east standard_name : longitude valid_min : -180.0 valid_max : 180.0 Array Chunk Bytes 6.68 kiB 128 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float32 numpy.ndarray
1710 1
elon
(number_of_lines)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Ending Longitude units : degrees_east standard_name : longitude valid_min : -180.0 valid_max : 180.0 Array Chunk Bytes 6.68 kiB 128 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float32 numpy.ndarray
1710 1
slat
(number_of_lines)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Starting Latitude units : degrees_north standard_name : latitude valid_min : -90.0 valid_max : 90.0 Array Chunk Bytes 6.68 kiB 128 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float32 numpy.ndarray
1710 1
clat
(number_of_lines)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Center Latitude units : degrees_north standard_name : latitude valid_min : -90.0 valid_max : 90.0 Array Chunk Bytes 6.68 kiB 128 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float32 numpy.ndarray
1710 1
elat
(number_of_lines)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Ending Latitude units : degrees_north standard_name : latitude valid_min : -90.0 valid_max : 90.0 Array Chunk Bytes 6.68 kiB 128 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float32 numpy.ndarray
1710 1
csol_z
(number_of_lines)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Center Solar Zenith Angle units : degree valid_min : -90.0 valid_max : 90.0 Array Chunk Bytes 6.68 kiB 128 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float32 numpy.ndarray
1710 1
/geophysical_data(7) Dimensions: number_of_lines : 1710pixels_per_line : 1272wavelength_3d : 172Data variables: (7)
Rrs
(number_of_lines, pixels_per_line, wavelength_3d)
float32
dask.array<chunksize=(32, 256, 40), meta=np.ndarray>
long_name : Remote sensing reflectance units : sr^-1 standard_name : surface_ratio_of_upwelling_radiance_emerging_from_sea_water_to_downwelling_radiative_flux_in_air valid_min : -30000 valid_max : 25000 Array Chunk Bytes 1.39 GiB 1.25 MiB Shape (1710, 1272, 172) (32, 256, 40) Dask graph 1350 chunks in 2 graph layers Data type float32 numpy.ndarray
172 1272 1710
Rrs_unc
(number_of_lines, pixels_per_line, wavelength_3d)
float32
dask.array<chunksize=(32, 256, 40), meta=np.ndarray>
long_name : Uncertainty in remote sensing reflectance units : sr^-1 valid_min : -30000 valid_max : 30000 Array Chunk Bytes 1.39 GiB 1.25 MiB Shape (1710, 1272, 172) (32, 256, 40) Dask graph 1350 chunks in 2 graph layers Data type float32 numpy.ndarray
172 1272 1710
aot_865
(number_of_lines, pixels_per_line)
float32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Aerosol optical thickness at 865 nm standard_name : atmosphere_optical_thickness_due_to_ambient_aerosol valid_min : 0 valid_max : 30000 Array Chunk Bytes 8.30 MiB 1.24 MiB Shape (1710, 1272) (256, 1272) Dask graph 7 chunks in 2 graph layers Data type float32 numpy.ndarray
1272 1710
angstrom
(number_of_lines, pixels_per_line)
float32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Aerosol Angstrom exponent, 443 to 865 nm standard_name : aerosol_angstrom_exponent valid_min : -30000 valid_max : 5000 Array Chunk Bytes 8.30 MiB 1.24 MiB Shape (1710, 1272) (256, 1272) Dask graph 7 chunks in 2 graph layers Data type float32 numpy.ndarray
1272 1710
avw
(number_of_lines, pixels_per_line)
float32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Apparent Visible Wavelength units : nm valid_min : 400.0 valid_max : 700.0 reference : Vandermeulen, R. A., Mannino, A., Craig, S.E., Werdell, P.J., 2020: 150 shades of green: Using the full spectrum of remote sensing reflectance to elucidate color shifts in the ocean, Remote Sensing of Environment, 247, 111900, https://doi.org/10.1016/j.rse.2020.111900, https://doi.org/10.5067/KAROCHG01RYJ Array Chunk Bytes 8.30 MiB 1.24 MiB Shape (1710, 1272) (256, 1272) Dask graph 7 chunks in 2 graph layers Data type float32 numpy.ndarray
1272 1710
nflh
(number_of_lines, pixels_per_line)
float32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Normalized Fluorescence Line Height units : W m^-2 um^-1 sr^-1 valid_min : -26471 valid_max : 32353 reference : Behrenfeld, M.J., Westberry, T.K., Boss, E.S., O'Malley, R.T., Siegel, D.A., Wiggert, J.D., Franz, B.A., McClain, C.R., Feldman, G.C., Doney, S.C., Moore, J.K., Dall'Olmo, G., Milligan, A.J., Lima, I., and Mahowald, N.: Satellite-detected fluorescence reveals global physiology of ocean phytoplankton, Biogeosciences, 6, 779-794, doi:10.5194/bg-6-779-2009, 2009. Array Chunk Bytes 8.30 MiB 1.24 MiB Shape (1710, 1272) (256, 1272) Dask graph 7 chunks in 2 graph layers Data type float32 numpy.ndarray
1272 1710
l2_flags
(number_of_lines, pixels_per_line)
int32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Level-2 Processing Flags valid_min : -2147483648 valid_max : 2147483647 flag_masks : [ 1 2 4 8 16 3264 128 256 512 1024 20484096 8192 16384 32768 65536 131072262144 524288 1048576 2097152 4194304 838860816777216 33554432 67108864 134217728 268435456 5368709121073741824 -2147483648] flag_meanings : ATMFAIL LAND PRODWARN HIGLINT HILT HISATZEN COASTZ SPARE STRAYLIGHT CLDICE COCCOLITH TURBIDW HISOLZEN SPARE LOWLW CHLFAIL NAVWARN ABSAER SPARE MAXAERITER MODGLINT CHLWARN ATMWARN OPSHAL SEAICE NAVFAIL FILTER SPARE BOWTIEDEL HIPOL PRODFAIL SPARE Array Chunk Bytes 8.30 MiB 1.24 MiB Shape (1710, 1272) (256, 1272) Dask graph 7 chunks in 2 graph layers Data type int32 numpy.ndarray
1272 1710
/navigation_data(6) Dimensions: number_of_lines : 1710pixels_per_line : 1272Data variables: (3)
longitude
(number_of_lines, pixels_per_line)
float32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Longitude units : degrees_east standard_name : longitude valid_min : -180.0 valid_max : 180.0 Array Chunk Bytes 8.30 MiB 1.24 MiB Shape (1710, 1272) (256, 1272) Dask graph 7 chunks in 2 graph layers Data type float32 numpy.ndarray
1272 1710
latitude
(number_of_lines, pixels_per_line)
float32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Latitude units : degrees_north standard_name : latitude valid_min : -90.0 valid_max : 90.0 Array Chunk Bytes 8.30 MiB 1.24 MiB Shape (1710, 1272) (256, 1272) Dask graph 7 chunks in 2 graph layers Data type float32 numpy.ndarray
1272 1710
tilt
(number_of_lines)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Sensor tilt angle units : degree valid_min : -25.0 valid_max : 25.0 Array Chunk Bytes 6.68 kiB 128 B Shape (1710,) (32,) Dask graph 54 chunks in 2 graph layers Data type float32 numpy.ndarray
1710 1
Attributes: (3)
gringpointlongitude : [-75.3737 -51.710373 -54.89105 -55.18162 -82.05421 -81.159195] gringpointlatitude : [ 3.1425157 8.132527 28.826893 31.327667 25.995872 23.552532 ] gringpointsequence : [1 2 3 4 5 6]
/processing_control(289) Attributes: (5)
software_name : l2gen software_version : 9.11.0-09b1279b9 input_sources : PACE_OCI.20240613T171120.L1B.V3.nc,oci_gas_transmittance_cia_amf_v3.3.nc,GMAO_MERRA2.20240613T170000.MET.nc,GMAO_MERRA2.20240613T180000.MET.nc,GMAO_MERRA2.20240613T180000.MET.nc,GMAO_MERRA2.20240613T170000.MET.nc,GMAO_MERRA2.20240613T180000.MET.nc,GMAO_MERRA2.20240613T180000.MET.nc,GMAO_MERRA2.20240613T150000.PROFILE.nc,GMAO_MERRA2.20240613T180000.PROFILE.nc,GMAO_MERRA2.20240613T180000.PROFILE.nc,GMAO_MERRA2.20240613T170000.AER.nc,GMAO_MERRA2.20240613T180000.AER.nc,GMAO_MERRA2.20240613T180000.AER.nc,anc_cor_file_28jan2014.nc,morel_fq_hyperspectral.nc,aerosol_oci,gebco_ocssw_v2020.nc,gebco_ocssw_v2020.nc,gebco_ocssw_v2020.nc,mld_climatology_woa1994.hdf,20240613120000-CMC-L4_GHRSST-SSTfnd-CMC0.1deg-GLOB-v02.0-fv03.0.nc,20240613120000-CMC-L4_GHRSST-SSTfnd-CMC0.1deg-GLOB-v02.0-fv03.0.nc,sss_climatology_woa2009.hdf,no2_climatology_v2013.hdf,alpha510_climatology.hdf,taua865_climatology.hdf,calcite_table-20170109.txt,owmc_lut.hdf,water_spectra.nc,oci_gains_v3.1_20250722.nc calibration_data : oci_gains_v3.1_20250722.nc mask_names : ATMFAIL,LAND,CLDICE,HILT Attributes: (47)
title : OCI Level-2 Data AOP product_name : PACE_OCI.20240613T171120.L2.OC_AOP.V3_1.nc processing_version : 3.1 history : l2gen par=/data18/sdpsoper/vdc/vpu37/workbuf/PACE_OCI.20240613T171120.L1B.V3.nc.param metafile=PACE_OCI.20240613T171120.L2.OC_AOP.V3_1.nc.meta instrument : OCI platform : PACE Conventions : CF-1.8, ACDD-1.3 license : https://science.nasa.gov/earth-science/earth-science-data/data-information-policy/ naming_authority : gov.nasa.gsfc.sci.oceandata id : 3.1/L2/PACE_OCI.20240613T171120.L2.OC_AOP.V3_1.nc date_created : 2025-09-19T23:06:47.000Z standard_name_vocabulary : CF Standard Name Table v36 institution : NASA Goddard Space Flight Center, Ocean Ecology Laboratory, Ocean Biology Processing Group creator_name : NASA/GSFC/OBPG creator_email : data@oceancolor.gsfc.nasa.gov creator_url : https://oceandata.sci.gsfc.nasa.gov project : Ocean Biology Processing Group (NASA/GSFC/OBPG) publisher_name : NASA/GSFC/OBPG publisher_url : https://oceandata.sci.gsfc.nasa.gov publisher_email : data@oceancolor.gsfc.nasa.gov geospatial_bounds_crs : EPSG:4326 identifier_product_doi_authority : http://dx.doi.org identifier_product_doi : 10.5067/PACE/OCI/L2/OC_AOP/3.1 processing_level : L2 cdm_data_type : swath spatialResolution : 1000 m time_coverage_start : 2024-06-13T17:11:20.152Z time_coverage_end : 2024-06-13T17:16:20.035Z start_center_longitude : -63.717476 start_center_latitude : 6.2693677 end_center_longitude : -68.846 end_center_latitude : 28.819891 northernmost_latitude : 31.327667 southernmost_latitude : 3.1425157 easternmost_longitude : -51.710373 westernmost_longitude : -82.05421 geospatial_lat_units : degrees_north geospatial_lon_units : degrees_east geospatial_lat_max : 31.327667 geospatial_lat_min : 3.1425157 geospatial_lon_max : -51.710373 geospatial_lon_min : -82.05421 startDirection : Ascending endDirection : Ascending day_night_flag : Day earth_sun_distance_correction : 0.9694168567657471 geospatial_bounds : POLYGON ((-55.18162 31.32767, -82.05421 25.99587, -75.37370 3.14252, -51.71037 8.13253, -55.18162 31.32767))
# we could use xarray_open="datatree" but "dataset" tends to be faster here
pace_l2 = { 'xarray_open' : 'dataset' , 'merge' : [ '/geophysical_data' , '/navigation_data' ]}
plan . open_dataset ( 0 , open_method = pace_l2 )
open_method: {'xarray_open': 'dataset', 'merge': ['/geophysical_data', '/navigation_data'], 'open_kwargs': {'chunks': {}, 'engine': 'h5netcdf', 'decode_timedelta': False}, 'coords': 'auto', 'set_coords': True, 'dim_renames': None, 'auto_align_phony_dims': None, 'merge_kwargs': {}}
<xarray.Dataset> Size: 3GB
Dimensions: (number_of_lines: 1710, pixels_per_line: 1272, wavelength_3d: 172)
Coordinates:
longitude (number_of_lines, pixels_per_line) float32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
latitude (number_of_lines, pixels_per_line) float32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
Dimensions without coordinates: number_of_lines, pixels_per_line, wavelength_3d
Data variables:
Rrs (number_of_lines, pixels_per_line, wavelength_3d) float32 1GB dask.array<chunksize=(32, 256, 40), meta=np.ndarray>
Rrs_unc (number_of_lines, pixels_per_line, wavelength_3d) float32 1GB dask.array<chunksize=(32, 256, 40), meta=np.ndarray>
aot_865 (number_of_lines, pixels_per_line) float32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
angstrom (number_of_lines, pixels_per_line) float32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
avw (number_of_lines, pixels_per_line) float32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
nflh (number_of_lines, pixels_per_line) float32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
l2_flags (number_of_lines, pixels_per_line) int32 9MB dask.array<chunksize=(256, 1272), meta=np.ndarray>
tilt (number_of_lines) float32 7kB dask.array<chunksize=(32,), meta=np.ndarray> Dimensions: number_of_lines : 1710pixels_per_line : 1272wavelength_3d : 172Coordinates: (2)
longitude
(number_of_lines, pixels_per_line)
float32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Longitude units : degrees_east standard_name : longitude valid_min : -180.0 valid_max : 180.0
Array
Chunk
Bytes
8.30 MiB
1.24 MiB
Shape
(1710, 1272)
(256, 1272)
Dask graph
7 chunks in 2 graph layers
Data type
float32 numpy.ndarray
1272
1710
latitude
(number_of_lines, pixels_per_line)
float32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Latitude units : degrees_north standard_name : latitude valid_min : -90.0 valid_max : 90.0
Array
Chunk
Bytes
8.30 MiB
1.24 MiB
Shape
(1710, 1272)
(256, 1272)
Dask graph
7 chunks in 2 graph layers
Data type
float32 numpy.ndarray
1272
1710
Data variables: (8)
Rrs
(number_of_lines, pixels_per_line, wavelength_3d)
float32
dask.array<chunksize=(32, 256, 40), meta=np.ndarray>
long_name : Remote sensing reflectance units : sr^-1 standard_name : surface_ratio_of_upwelling_radiance_emerging_from_sea_water_to_downwelling_radiative_flux_in_air valid_min : -30000 valid_max : 25000
Array
Chunk
Bytes
1.39 GiB
1.25 MiB
Shape
(1710, 1272, 172)
(32, 256, 40)
Dask graph
1350 chunks in 2 graph layers
Data type
float32 numpy.ndarray
172
1272
1710
Rrs_unc
(number_of_lines, pixels_per_line, wavelength_3d)
float32
dask.array<chunksize=(32, 256, 40), meta=np.ndarray>
long_name : Uncertainty in remote sensing reflectance units : sr^-1 valid_min : -30000 valid_max : 30000
Array
Chunk
Bytes
1.39 GiB
1.25 MiB
Shape
(1710, 1272, 172)
(32, 256, 40)
Dask graph
1350 chunks in 2 graph layers
Data type
float32 numpy.ndarray
172
1272
1710
aot_865
(number_of_lines, pixels_per_line)
float32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Aerosol optical thickness at 865 nm standard_name : atmosphere_optical_thickness_due_to_ambient_aerosol valid_min : 0 valid_max : 30000
Array
Chunk
Bytes
8.30 MiB
1.24 MiB
Shape
(1710, 1272)
(256, 1272)
Dask graph
7 chunks in 2 graph layers
Data type
float32 numpy.ndarray
1272
1710
angstrom
(number_of_lines, pixels_per_line)
float32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Aerosol Angstrom exponent, 443 to 865 nm standard_name : aerosol_angstrom_exponent valid_min : -30000 valid_max : 5000
Array
Chunk
Bytes
8.30 MiB
1.24 MiB
Shape
(1710, 1272)
(256, 1272)
Dask graph
7 chunks in 2 graph layers
Data type
float32 numpy.ndarray
1272
1710
avw
(number_of_lines, pixels_per_line)
float32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Apparent Visible Wavelength units : nm valid_min : 400.0 valid_max : 700.0 reference : Vandermeulen, R. A., Mannino, A., Craig, S.E., Werdell, P.J., 2020: 150 shades of green: Using the full spectrum of remote sensing reflectance to elucidate color shifts in the ocean, Remote Sensing of Environment, 247, 111900, https://doi.org/10.1016/j.rse.2020.111900, https://doi.org/10.5067/KAROCHG01RYJ
Array
Chunk
Bytes
8.30 MiB
1.24 MiB
Shape
(1710, 1272)
(256, 1272)
Dask graph
7 chunks in 2 graph layers
Data type
float32 numpy.ndarray
1272
1710
nflh
(number_of_lines, pixels_per_line)
float32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Normalized Fluorescence Line Height units : W m^-2 um^-1 sr^-1 valid_min : -26471 valid_max : 32353 reference : Behrenfeld, M.J., Westberry, T.K., Boss, E.S., O'Malley, R.T., Siegel, D.A., Wiggert, J.D., Franz, B.A., McClain, C.R., Feldman, G.C., Doney, S.C., Moore, J.K., Dall'Olmo, G., Milligan, A.J., Lima, I., and Mahowald, N.: Satellite-detected fluorescence reveals global physiology of ocean phytoplankton, Biogeosciences, 6, 779-794, doi:10.5194/bg-6-779-2009, 2009.
Array
Chunk
Bytes
8.30 MiB
1.24 MiB
Shape
(1710, 1272)
(256, 1272)
Dask graph
7 chunks in 2 graph layers
Data type
float32 numpy.ndarray
1272
1710
l2_flags
(number_of_lines, pixels_per_line)
int32
dask.array<chunksize=(256, 1272), meta=np.ndarray>
long_name : Level-2 Processing Flags valid_min : -2147483648 valid_max : 2147483647 flag_masks : [ 1 2 4 8 16 32
64 128 256 512 1024 2048
4096 8192 16384 32768 65536 131072
262144 524288 1048576 2097152 4194304 8388608
16777216 33554432 67108864 134217728 268435456 536870912
1073741824 -2147483648] flag_meanings : ATMFAIL LAND PRODWARN HIGLINT HILT HISATZEN COASTZ SPARE STRAYLIGHT CLDICE COCCOLITH TURBIDW HISOLZEN SPARE LOWLW CHLFAIL NAVWARN ABSAER SPARE MAXAERITER MODGLINT CHLWARN ATMWARN OPSHAL SEAICE NAVFAIL FILTER SPARE BOWTIEDEL HIPOL PRODFAIL SPARE
Array
Chunk
Bytes
8.30 MiB
1.24 MiB
Shape
(1710, 1272)
(256, 1272)
Dask graph
7 chunks in 2 graph layers
Data type
int32 numpy.ndarray
1272
1710
tilt
(number_of_lines)
float32
dask.array<chunksize=(32,), meta=np.ndarray>
long_name : Sensor tilt angle units : degree valid_min : -25.0 valid_max : 25.0
Array
Chunk
Bytes
6.68 kiB
128 B
Shape
(1710,)
(32,)
Dask graph
54 chunks in 2 graph layers
Data type
float32 numpy.ndarray
1710
1
Get the matchups using that plan
pc.matchup() will open each L2 granule as a DataTree and merges all groups into a flat dataset. The spatial method will automatically use "kdtree" for non-gridded data. You can also try spatial_method="xoak-kdtree", which uses a similar algorithm.
Notice, that point 0 is matched to 2 granules and so has 2 rows with the same pc_id. Many matchups are NaN because there is no data (cloudy) for that lat/lon point.
%% time
# spatial_method="auto" defaults to "kdtree" in this case
res = pc . matchup ( plan , variables = [ "Rrs" ], open_method = pace_l2 )
CPU times: user 22.4 s, sys: 2.21 s, total: 24.7 s
Wall time: 43.9 s
lat
lon
time
pc_id
granule_id
granule_time
granule_lat
granule_lon
Rrs_0
Rrs_1
...
Rrs_162
Rrs_163
Rrs_164
Rrs_165
Rrs_166
Rrs_167
Rrs_168
Rrs_169
Rrs_170
Rrs_171
0
27.3835
-82.7375
2024-06-13 12:00:00
0
https://obdaac-tea.earthdatacloud.nasa.gov/ob-...
2024-06-13 17:18:49+00:00
27.443144
-82.612923
NaN
NaN
...
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
1
27.3835
-82.7375
2024-06-13 12:00:00
0
https://obdaac-tea.earthdatacloud.nasa.gov/ob-...
2024-06-13 18:52:08+00:00
27.383293
-82.721527
NaN
NaN
...
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
2
27.1190
-82.7125
2024-06-14 12:00:00
1
https://obdaac-tea.earthdatacloud.nasa.gov/ob-...
2024-06-14 17:53:34+00:00
27.101389
-82.717186
0.01299
0.012946
...
0.000238
0.000228
0.000198
0.000194
0.000186
0.000172
0.000152
0.000122
0.000108
0.000094
3
26.9435
-82.8170
2024-06-14 12:00:00
2
https://obdaac-tea.earthdatacloud.nasa.gov/ob-...
2024-06-14 17:53:34+00:00
26.954554
-82.810219
NaN
NaN
...
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
4
26.6875
-82.8065
2024-06-14 12:00:00
3
https://obdaac-tea.earthdatacloud.nasa.gov/ob-...
2024-06-14 17:53:34+00:00
26.703817
-82.817726
NaN
NaN
...
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
5 rows × 180 columns
%% time
# we can specify to use the xoak package
res2 = pc . matchup ( plan ,
spatial_method = "xoak-kdtree" ,
variables = [ "Rrs" ],
open_method = pace_l2 )
CPU times: user 26.2 s, sys: 1.22 s, total: 27.4 s
Wall time: 42.7 s