Constraint Expressions: Server-side Subsetting#

Motivation#

Many OPeNDAP servers contain collections of datasets that in aggregation describe a complete dataset (e.g. a multi-year simulation). In some cases, each dataset may contain \(\sim O(10-100)\) of variables in them – this is particularly true for Level 2 data, see for example this ATLAS03 dataset from NASA. This means PyDAP must parse 100s of variables per file. PyDAP is a fast parser of DMRs (the DAP4 metadata response), but:

  1. PyDAP does not (yet) aggregate datasets nor URLs.

  2. PyDAP does not make CF-checks, nor does it define label-based operations.

xarray, on the other hand, allows for parallel read and aggregation of multiple datasets. However, despite the awesome parallel features of xarray, it can be slow during the aggregation of multiple datasets because it performs a number of checks on the metadata so that the collection of files are “safe” to open and operate upon, according to the internal logics of xarray. This means that xarray makes extra checks to ensure safe label-based operations, and the time it takes can grow with the number of variables.

Note

Even though xarray hasa. method to drop variables from the virtual xarray.Dataset, it is only available after the dataset is created. This is, if you have 100s of files each with 100s of variables, but you are only interested in 2-3 variables per file, the client must parse and check all variables in all files, to create a dataset from which you will then drop all but the 2-3 variables of interest.

These, in combination, provide an obstacle for initial data exploration of collections of OPeNDAP datasets that contain many variables, Groups, among other complex types.

Approach#

One can add Constraint Expresions (CEs) to the dataset URL and sent it to the remote OPeNDAP server, to:

  1. Request a subset of variables, and

  2. Request a spatial subset of variables.

These CEs are increadible powerful from the user perspective because pydap, as a backend engine to xarray, can receive a much smaller DAP response from the remote OPeNDAP server. This is, the CEs inform the remote OPeNDAP server to subset close to the data. The response may be faster by \(\sim O(1)\) second overall, but when considering a 100s of URLs, the result can have a significant impact on the performance and user experience.

Below we review Constraint Expressions with real data on OPeNDAP servers. Because there are two distinct DAP Protocols (see Pydap as a client), we will review the two cases separately.

from pydap.client import open_url
import numpy as np
import matplotlib.pyplot as plt

Constraint Expressions in DAP4#

Here we demonstrate the use of CE in arrays of 1 and 2 dimensions, in two distinct datasets:

  1. ATLAS03, level 2 Data.

  2. Daily MUR Sea Surface Temperature, level 4 data provided by PODAAC at JPL.

Note

For more interesting examples, take a look at PACE example

ATLAS03#

This dataset has many nested Groups, with many variables in them. Say we are only interested in the variables:

  1. delta_time.

  2. lat_ph.

  3. lon_ph.

The tree variables lie within the Group heights, which in turn is nested in the Group with name gt3r.

Lets open the remote file naively, by requesting all the variables from the OPeNDAP server (Hyrax in this case)

data_url = 'http://test.opendap.org:8080/opendap/atlas03/ATL03_20200131234815_05540602_003_01.h5'
%%time
ds = open_url(data_url, protocol='dap4')
CPU times: user 2.87 s, sys: 12.1 ms, total: 2.88 s
Wall time: 5.01 s

Below, we print the entire tree directory within the HDF5 dataset

ds.tree()
.ATL03_20200131234815_05540602_003_01.h5
├──orbit_info
│  ├──crossing_time
│  ├──sc_orient_time
│  ├──orbit_number
│  ├──rgt
│  ├──sc_orient
│  ├──cycle_number
│  └──lan
├──METADATA
│  ├──AcquisitionInformation
│  │  ├──lidar
│  │  ├──lidarDocument
│  │  ├──platform
│  │  └──platformDocument
│  ├──DataQuality
│  │  ├──CompletenessOmission
│  │  └──DomainConsistency
│  ├──ProductSpecificationDocument
│  ├──SeriesIdentification
│  ├──DatasetIdentification
│  ├──Extent
│  ├──QADatasetIdentification
│  ├──Lineage
│  │  ├──ANC25-03
│  │  ├──ANC03
│  │  ├──Control
│  │  ├──ANC28
│  │  ├──ANC12-02
│  │  ├──ANC41
│  │  ├──ANC08
│  │  ├──ANC06-02
│  │  ├──ANC06-03
│  │  ├──ANC22
│  │  ├──ANC11
│  │  ├──ANC04
│  │  ├──ANC38-03
│  │  ├──ANC01
│  │  ├──ANC29
│  │  ├──ANC12-01
│  │  ├──ANC05
│  │  ├──ANC06-01
│  │  ├──ANC36-03
│  │  ├──ANC07
│  │  ├──ANC26-03
│  │  ├──ATL02
│  │  ├──ANC19
│  │  └──ANC23
│  └──ProcessStep
│     ├──Browse
│     ├──Metadata
│     ├──PGE
│     └──QA
├──gt1r
│  ├──bckgrd_atlas
│  │  ├──delta_time
│  │  ├──tlm_height_band1
│  │  ├──bckgrd_rate
│  │  ├──tlm_top_band1
│  │  ├──tlm_top_band2
│  │  ├──bckgrd_int_height_reduced
│  │  ├──bckgrd_hist_top
│  │  ├──bckgrd_counts_reduced
│  │  ├──tlm_height_band2
│  │  ├──bckgrd_int_height
│  │  ├──pce_mframe_cnt
│  │  └──bckgrd_counts
│  ├──geolocation
│  │  ├──reference_photon_lat
│  │  ├──delta_time
│  │  ├──range_bias_corr
│  │  ├──neutat_delay_derivative
│  │  ├──reference_photon_lon
│  │  ├──sigma_across
│  │  ├──sigma_lon
│  │  ├──ref_azimuth
│  │  ├──ref_elev
│  │  ├──neutat_ht
│  │  ├──ph_index_beg
│  │  ├──solar_azimuth
│  │  ├──surf_type
│  │  ├──sigma_lat
│  │  ├──tx_pulse_width_lower
│  │  ├──sigma_along
│  │  ├──tx_pulse_skew_est
│  │  ├──tx_pulse_energy
│  │  ├──tx_pulse_width_upper
│  │  ├──sigma_h
│  │  ├──podppd_flag
│  │  ├──velocity_sc
│  │  ├──full_sat_fract
│  │  ├──segment_id
│  │  ├──near_sat_fract
│  │  ├──segment_ph_cnt
│  │  ├──solar_elevation
│  │  ├──bounce_time_offset
│  │  ├──segment_length
│  │  ├──reference_photon_index
│  │  ├──altitude_sc
│  │  ├──segment_dist_x
│  │  └──neutat_delay_total
│  ├──geophys_corr
│  │  ├──delta_time
│  │  ├──dem_flag
│  │  ├──tide_ocean
│  │  ├──tide_earth
│  │  ├──dac
│  │  ├──tide_load
│  │  ├──dem_h
│  │  ├──tide_equilibrium
│  │  ├──geoid
│  │  ├──tide_oc_pole
│  │  └──tide_pole
│  ├──signal_find_output
│  │  ├──land
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  ├──sea_ice
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  ├──land_ice
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  └──inlandwater
│  │     ├──delta_time
│  │     ├──bckgrd_sigma
│  │     ├──t_pc_delta
│  │     ├──bckgrd_mean
│  │     └──z_pc_delta
│  └──heights
│     ├──delta_time
│     ├──lat_ph
│     ├──dist_ph_along
│     ├──signal_conf_ph
│     ├──ph_id_pulse
│     ├──h_ph
│     ├──ph_id_channel
│     ├──lon_ph
│     ├──ph_id_count
│     ├──pce_mframe_cnt
│     └──dist_ph_across
├──gt2r
│  ├──bckgrd_atlas
│  │  ├──delta_time
│  │  ├──tlm_height_band1
│  │  ├──bckgrd_rate
│  │  ├──tlm_top_band1
│  │  ├──tlm_top_band2
│  │  ├──bckgrd_int_height_reduced
│  │  ├──bckgrd_hist_top
│  │  ├──bckgrd_counts_reduced
│  │  ├──tlm_height_band2
│  │  ├──bckgrd_int_height
│  │  ├──pce_mframe_cnt
│  │  └──bckgrd_counts
│  ├──geolocation
│  │  ├──reference_photon_lat
│  │  ├──delta_time
│  │  ├──range_bias_corr
│  │  ├──neutat_delay_derivative
│  │  ├──reference_photon_lon
│  │  ├──sigma_across
│  │  ├──sigma_lon
│  │  ├──ref_azimuth
│  │  ├──ref_elev
│  │  ├──neutat_ht
│  │  ├──ph_index_beg
│  │  ├──solar_azimuth
│  │  ├──surf_type
│  │  ├──sigma_lat
│  │  ├──tx_pulse_width_lower
│  │  ├──sigma_along
│  │  ├──tx_pulse_skew_est
│  │  ├──tx_pulse_energy
│  │  ├──tx_pulse_width_upper
│  │  ├──sigma_h
│  │  ├──podppd_flag
│  │  ├──velocity_sc
│  │  ├──full_sat_fract
│  │  ├──segment_id
│  │  ├──near_sat_fract
│  │  ├──segment_ph_cnt
│  │  ├──solar_elevation
│  │  ├──bounce_time_offset
│  │  ├──segment_length
│  │  ├──reference_photon_index
│  │  ├──altitude_sc
│  │  ├──segment_dist_x
│  │  └──neutat_delay_total
│  ├──geophys_corr
│  │  ├──delta_time
│  │  ├──dem_flag
│  │  ├──tide_ocean
│  │  ├──tide_earth
│  │  ├──dac
│  │  ├──tide_load
│  │  ├──dem_h
│  │  ├──tide_equilibrium
│  │  ├──geoid
│  │  ├──tide_oc_pole
│  │  └──tide_pole
│  ├──signal_find_output
│  │  ├──sea_ice
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  ├──land_ice
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  ├──land
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  └──inlandwater
│  │     ├──delta_time
│  │     ├──bckgrd_sigma
│  │     ├──t_pc_delta
│  │     ├──bckgrd_mean
│  │     └──z_pc_delta
│  └──heights
│     ├──delta_time
│     ├──lat_ph
│     ├──dist_ph_along
│     ├──signal_conf_ph
│     ├──ph_id_pulse
│     ├──h_ph
│     ├──ph_id_channel
│     ├──lon_ph
│     ├──ph_id_count
│     ├──pce_mframe_cnt
│     └──dist_ph_across
├──gt1l
│  ├──bckgrd_atlas
│  │  ├──delta_time
│  │  ├──tlm_height_band1
│  │  ├──bckgrd_rate
│  │  ├──tlm_top_band1
│  │  ├──tlm_top_band2
│  │  ├──bckgrd_int_height_reduced
│  │  ├──bckgrd_hist_top
│  │  ├──bckgrd_counts_reduced
│  │  ├──tlm_height_band2
│  │  ├──bckgrd_int_height
│  │  ├──pce_mframe_cnt
│  │  └──bckgrd_counts
│  ├──geolocation
│  │  ├──reference_photon_lat
│  │  ├──delta_time
│  │  ├──range_bias_corr
│  │  ├──neutat_delay_derivative
│  │  ├──reference_photon_lon
│  │  ├──sigma_across
│  │  ├──sigma_lon
│  │  ├──ref_azimuth
│  │  ├──ref_elev
│  │  ├──neutat_ht
│  │  ├──ph_index_beg
│  │  ├──solar_azimuth
│  │  ├──surf_type
│  │  ├──sigma_lat
│  │  ├──tx_pulse_width_lower
│  │  ├──sigma_along
│  │  ├──tx_pulse_skew_est
│  │  ├──tx_pulse_energy
│  │  ├──tx_pulse_width_upper
│  │  ├──sigma_h
│  │  ├──podppd_flag
│  │  ├──velocity_sc
│  │  ├──full_sat_fract
│  │  ├──segment_id
│  │  ├──near_sat_fract
│  │  ├──segment_ph_cnt
│  │  ├──solar_elevation
│  │  ├──bounce_time_offset
│  │  ├──segment_length
│  │  ├──reference_photon_index
│  │  ├──altitude_sc
│  │  ├──segment_dist_x
│  │  └──neutat_delay_total
│  ├──geophys_corr
│  │  ├──delta_time
│  │  ├──dem_flag
│  │  ├──tide_ocean
│  │  ├──tide_earth
│  │  ├──dac
│  │  ├──tide_load
│  │  ├──dem_h
│  │  ├──tide_equilibrium
│  │  ├──geoid
│  │  ├──tide_oc_pole
│  │  └──tide_pole
│  ├──signal_find_output
│  │  ├──land
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  ├──sea_ice
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  ├──land_ice
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  └──inlandwater
│  │     ├──delta_time
│  │     ├──bckgrd_sigma
│  │     ├──t_pc_delta
│  │     ├──bckgrd_mean
│  │     └──z_pc_delta
│  └──heights
│     ├──delta_time
│     ├──lat_ph
│     ├──dist_ph_along
│     ├──signal_conf_ph
│     ├──ph_id_pulse
│     ├──h_ph
│     ├──ph_id_channel
│     ├──lon_ph
│     ├──ph_id_count
│     ├──pce_mframe_cnt
│     └──dist_ph_across
├──quality_assessment
│  ├──gt1r
│  │  ├──qa_perc_signal_conf_ph_high
│  │  ├──qa_perc_signal_conf_ph_low
│  │  ├──qa_perc_signal_conf_ph_med
│  │  ├──qa_total_signal_conf_ph_high
│  │  ├──qa_perc_surf_type
│  │  ├──qa_total_signal_conf_ph_low
│  │  └──qa_total_signal_conf_ph_med
│  ├──gt2r
│  │  ├──qa_perc_signal_conf_ph_high
│  │  ├──qa_perc_signal_conf_ph_low
│  │  ├──qa_perc_signal_conf_ph_med
│  │  ├──qa_total_signal_conf_ph_high
│  │  ├──qa_perc_surf_type
│  │  ├──qa_total_signal_conf_ph_low
│  │  └──qa_total_signal_conf_ph_med
│  ├──gt1l
│  │  ├──qa_perc_signal_conf_ph_high
│  │  ├──qa_perc_signal_conf_ph_low
│  │  ├──qa_perc_signal_conf_ph_med
│  │  ├──qa_total_signal_conf_ph_high
│  │  ├──qa_perc_surf_type
│  │  ├──qa_total_signal_conf_ph_low
│  │  └──qa_total_signal_conf_ph_med
│  ├──gt3l
│  │  ├──qa_perc_signal_conf_ph_high
│  │  ├──qa_perc_signal_conf_ph_low
│  │  ├──qa_perc_signal_conf_ph_med
│  │  ├──qa_total_signal_conf_ph_high
│  │  ├──qa_perc_surf_type
│  │  ├──qa_total_signal_conf_ph_low
│  │  └──qa_total_signal_conf_ph_med
│  ├──gt2l
│  │  ├──qa_perc_signal_conf_ph_high
│  │  ├──qa_perc_signal_conf_ph_low
│  │  ├──qa_perc_signal_conf_ph_med
│  │  ├──qa_total_signal_conf_ph_high
│  │  ├──qa_perc_surf_type
│  │  ├──qa_total_signal_conf_ph_low
│  │  └──qa_total_signal_conf_ph_med
│  ├──gt3r
│  │  ├──qa_perc_signal_conf_ph_high
│  │  ├──qa_perc_signal_conf_ph_low
│  │  ├──qa_perc_signal_conf_ph_med
│  │  ├──qa_total_signal_conf_ph_high
│  │  ├──qa_perc_surf_type
│  │  ├──qa_total_signal_conf_ph_low
│  │  └──qa_total_signal_conf_ph_med
│  ├──delta_time
│  ├──qa_granule_fail_reason
│  └──qa_granule_pass_fail
├──atlas_impulse_response
│  ├──pce1_spot1
│  │  └──tep_histogram
│  │     ├──tep_hist_time
│  │     ├──tep_tod
│  │     ├──tep_duration
│  │     ├──reference_tep_flag
│  │     ├──tep_hist_sum
│  │     ├──tep_hist
│  │     └──tep_bckgrd
│  └──pce2_spot3
│     └──tep_histogram
│        ├──tep_hist_time
│        ├──tep_tod
│        ├──tep_duration
│        ├──reference_tep_flag
│        ├──tep_hist_sum
│        ├──tep_hist
│        └──tep_bckgrd
├──gt3l
│  ├──bckgrd_atlas
│  │  ├──delta_time
│  │  ├──tlm_height_band1
│  │  ├──bckgrd_rate
│  │  ├──tlm_top_band1
│  │  ├──tlm_top_band2
│  │  ├──bckgrd_int_height_reduced
│  │  ├──bckgrd_hist_top
│  │  ├──bckgrd_counts_reduced
│  │  ├──tlm_height_band2
│  │  ├──bckgrd_int_height
│  │  ├──pce_mframe_cnt
│  │  └──bckgrd_counts
│  ├──geolocation
│  │  ├──reference_photon_lat
│  │  ├──delta_time
│  │  ├──range_bias_corr
│  │  ├──neutat_delay_derivative
│  │  ├──reference_photon_lon
│  │  ├──sigma_across
│  │  ├──sigma_lon
│  │  ├──ref_azimuth
│  │  ├──ref_elev
│  │  ├──neutat_ht
│  │  ├──ph_index_beg
│  │  ├──solar_azimuth
│  │  ├──surf_type
│  │  ├──sigma_lat
│  │  ├──tx_pulse_width_lower
│  │  ├──sigma_along
│  │  ├──tx_pulse_skew_est
│  │  ├──tx_pulse_energy
│  │  ├──tx_pulse_width_upper
│  │  ├──sigma_h
│  │  ├──podppd_flag
│  │  ├──velocity_sc
│  │  ├──full_sat_fract
│  │  ├──segment_id
│  │  ├──near_sat_fract
│  │  ├──segment_ph_cnt
│  │  ├──solar_elevation
│  │  ├──bounce_time_offset
│  │  ├──segment_length
│  │  ├──reference_photon_index
│  │  ├──altitude_sc
│  │  ├──segment_dist_x
│  │  └──neutat_delay_total
│  ├──geophys_corr
│  │  ├──delta_time
│  │  ├──dem_flag
│  │  ├──tide_ocean
│  │  ├──tide_earth
│  │  ├──dac
│  │  ├──tide_load
│  │  ├──dem_h
│  │  ├──tide_equilibrium
│  │  ├──geoid
│  │  ├──tide_oc_pole
│  │  └──tide_pole
│  ├──signal_find_output
│  │  ├──sea_ice
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  ├──land_ice
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  ├──land
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  └──inlandwater
│  │     ├──delta_time
│  │     ├──bckgrd_sigma
│  │     ├──t_pc_delta
│  │     ├──bckgrd_mean
│  │     └──z_pc_delta
│  └──heights
│     ├──delta_time
│     ├──lat_ph
│     ├──dist_ph_along
│     ├──signal_conf_ph
│     ├──ph_id_pulse
│     ├──h_ph
│     ├──ph_id_channel
│     ├──lon_ph
│     ├──ph_id_count
│     ├──pce_mframe_cnt
│     └──dist_ph_across
├──gt2l
│  ├──bckgrd_atlas
│  │  ├──delta_time
│  │  ├──tlm_height_band1
│  │  ├──bckgrd_rate
│  │  ├──tlm_top_band1
│  │  ├──tlm_top_band2
│  │  ├──bckgrd_int_height_reduced
│  │  ├──bckgrd_hist_top
│  │  ├──bckgrd_counts_reduced
│  │  ├──tlm_height_band2
│  │  ├──bckgrd_int_height
│  │  ├──pce_mframe_cnt
│  │  └──bckgrd_counts
│  ├──geolocation
│  │  ├──reference_photon_lat
│  │  ├──delta_time
│  │  ├──range_bias_corr
│  │  ├──neutat_delay_derivative
│  │  ├──reference_photon_lon
│  │  ├──sigma_across
│  │  ├──sigma_lon
│  │  ├──ref_azimuth
│  │  ├──ref_elev
│  │  ├──neutat_ht
│  │  ├──ph_index_beg
│  │  ├──solar_azimuth
│  │  ├──surf_type
│  │  ├──sigma_lat
│  │  ├──tx_pulse_width_lower
│  │  ├──sigma_along
│  │  ├──tx_pulse_skew_est
│  │  ├──tx_pulse_energy
│  │  ├──tx_pulse_width_upper
│  │  ├──sigma_h
│  │  ├──podppd_flag
│  │  ├──velocity_sc
│  │  ├──full_sat_fract
│  │  ├──segment_id
│  │  ├──near_sat_fract
│  │  ├──segment_ph_cnt
│  │  ├──solar_elevation
│  │  ├──bounce_time_offset
│  │  ├──segment_length
│  │  ├──reference_photon_index
│  │  ├──altitude_sc
│  │  ├──segment_dist_x
│  │  └──neutat_delay_total
│  ├──geophys_corr
│  │  ├──delta_time
│  │  ├──dem_flag
│  │  ├──tide_ocean
│  │  ├──tide_earth
│  │  ├──dac
│  │  ├──tide_load
│  │  ├──dem_h
│  │  ├──tide_equilibrium
│  │  ├──geoid
│  │  ├──tide_oc_pole
│  │  └──tide_pole
│  ├──signal_find_output
│  │  ├──sea_ice
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  ├──land_ice
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  ├──land
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  └──inlandwater
│  │     ├──delta_time
│  │     ├──bckgrd_sigma
│  │     ├──t_pc_delta
│  │     ├──bckgrd_mean
│  │     └──z_pc_delta
│  └──heights
│     ├──delta_time
│     ├──lat_ph
│     ├──dist_ph_along
│     ├──signal_conf_ph
│     ├──ph_id_pulse
│     ├──h_ph
│     ├──ph_id_channel
│     ├──lon_ph
│     ├──ph_id_count
│     ├──pce_mframe_cnt
│     └──dist_ph_across
├──ancillary_data
│  ├──calibrations
│  │  ├──dead_time_radiometric_signal_loss
│  │  │  ├──gt1l
│  │  │  │  ├──dead_time
│  │  │  │  ├──rad_corr
│  │  │  │  ├──strength
│  │  │  │  └──width
│  │  │  ├──gt2l
│  │  │  │  ├──dead_time
│  │  │  │  ├──rad_corr
│  │  │  │  ├──strength
│  │  │  │  └──width
│  │  │  ├──gt1r
│  │  │  │  ├──dead_time
│  │  │  │  ├──rad_corr
│  │  │  │  ├──strength
│  │  │  │  └──width
│  │  │  ├──gt2r
│  │  │  │  ├──dead_time
│  │  │  │  ├──rad_corr
│  │  │  │  ├──strength
│  │  │  │  └──width
│  │  │  ├──gt3l
│  │  │  │  ├──dead_time
│  │  │  │  ├──rad_corr
│  │  │  │  ├──strength
│  │  │  │  └──width
│  │  │  └──gt3r
│  │  │     ├──dead_time
│  │  │     ├──rad_corr
│  │  │     ├──strength
│  │  │     └──width
│  │  ├──first_photon_bias
│  │  │  ├──gt1l
│  │  │  │  ├──dead_time
│  │  │  │  ├──ffb_corr
│  │  │  │  ├──strength
│  │  │  │  └──width
│  │  │  ├──gt2l
│  │  │  │  ├──dead_time
│  │  │  │  ├──ffb_corr
│  │  │  │  ├──strength
│  │  │  │  └──width
│  │  │  ├──gt1r
│  │  │  │  ├──dead_time
│  │  │  │  ├──ffb_corr
│  │  │  │  ├──strength
│  │  │  │  └──width
│  │  │  ├──gt2r
│  │  │  │  ├──dead_time
│  │  │  │  ├──ffb_corr
│  │  │  │  ├──strength
│  │  │  │  └──width
│  │  │  ├──gt3l
│  │  │  │  ├──dead_time
│  │  │  │  ├──ffb_corr
│  │  │  │  ├──strength
│  │  │  │  └──width
│  │  │  └──gt3r
│  │  │     ├──dead_time
│  │  │     ├──ffb_corr
│  │  │     ├──strength
│  │  │     └──width
│  │  ├──low_link_impulse_response
│  │  │  ├──gt1r
│  │  │  │  ├──hist
│  │  │  │  └──total_events
│  │  │  ├──gt2r
│  │  │  │  ├──hist
│  │  │  │  └──total_events
│  │  │  ├──gt1l
│  │  │  │  ├──hist
│  │  │  │  └──total_events
│  │  │  ├──gt3l
│  │  │  │  ├──hist
│  │  │  │  └──total_events
│  │  │  ├──gt2l
│  │  │  │  ├──hist
│  │  │  │  └──total_events
│  │  │  ├──gt3r
│  │  │  │  ├──hist
│  │  │  │  └──total_events
│  │  │  ├──hist_x
│  │  │  ├──laser
│  │  │  ├──mode
│  │  │  ├──return_source
│  │  │  ├──num_bins
│  │  │  ├──temperature
│  │  │  ├──bin_width
│  │  │  └──side
│  │  ├──dead_time
│  │  │  ├──gt1r
│  │  │  │  ├──dead_time
│  │  │  │  └──sigma
│  │  │  ├──gt2r
│  │  │  │  ├──dead_time
│  │  │  │  └──sigma
│  │  │  ├──gt1l
│  │  │  │  ├──dead_time
│  │  │  │  └──sigma
│  │  │  ├──gt3l
│  │  │  │  ├──dead_time
│  │  │  │  └──sigma
│  │  │  ├──gt2l
│  │  │  │  ├──dead_time
│  │  │  │  └──sigma
│  │  │  ├──gt3r
│  │  │  │  ├──dead_time
│  │  │  │  └──sigma
│  │  │  ├──temperature
│  │  │  └──side
│  │  └──ds_channel
│  ├──atlas_engineering
│  │  ├──transmit
│  │  │  ├──tx_pulse_distribution
│  │  │  ├──tx_pulse_skew_est
│  │  │  ├──tx_pulse_thresh_lower
│  │  │  ├──tx_pulse_thresh_upper
│  │  │  ├──tx_pulse_width_lower
│  │  │  ├──tx_pulse_width_upper
│  │  │  └──tx_pulse_energy
│  │  ├──receiver
│  │  │  ├──rx_bckgrd_sensitivity
│  │  │  └──rx_return_sensitivity
│  │  ├──ds_gt
│  │  ├──ds_stat
│  │  ├──spd_ab_flag
│  │  ├──det_ab_flag
│  │  ├──lrs_ab_flag
│  │  ├──tams_ab_flag
│  │  ├──laser_12_flag
│  │  ├──pdu_ab_flag
│  │  ├──ph_uncorrelated_error
│  │  └──hvpc_ab_flag
│  ├──gt1r
│  │  └──signal_find_input
│  │     ├──sig_find_t_inc
│  │     ├──alpha_max
│  │     ├──delta_z_bg
│  │     ├──e_linfit_edit
│  │     ├──e_m
│  │     ├──snrlow
│  │     ├──nslw_v
│  │     ├──nphot_min
│  │     ├──delta_zmin
│  │     ├──delta_t_max
│  │     ├──lslant_flag
│  │     ├──n_delta_z2
│  │     ├──e_m_mult
│  │     ├──delta_t_min
│  │     ├──r2
│  │     ├──snrmed
│  │     ├──n_delta_z1
│  │     ├──min_fit_time_fact
│  │     ├──pc_bckgrd_flag
│  │     ├──t_gap_big
│  │     ├──e_a
│  │     ├──delta_zmax2
│  │     ├──nslw
│  │     ├──e_linfit_slant
│  │     ├──addpad_flag
│  │     ├──nbin_min
│  │     ├──htspanmin
│  │     ├──alpha_inc
│  │     ├──out_edit_flag
│  │     ├──delta_t_gap_min
│  │     ├──delta_t_lin_fit
│  │     └──r
│  ├──gt2r
│  │  └──signal_find_input
│  │     ├──sig_find_t_inc
│  │     ├──alpha_max
│  │     ├──delta_z_bg
│  │     ├──e_linfit_edit
│  │     ├──e_m
│  │     ├──snrlow
│  │     ├──nslw_v
│  │     ├──nphot_min
│  │     ├──delta_zmin
│  │     ├──delta_t_max
│  │     ├──lslant_flag
│  │     ├──n_delta_z2
│  │     ├──e_m_mult
│  │     ├──delta_t_min
│  │     ├──r2
│  │     ├──snrmed
│  │     ├──n_delta_z1
│  │     ├──min_fit_time_fact
│  │     ├──pc_bckgrd_flag
│  │     ├──t_gap_big
│  │     ├──e_a
│  │     ├──delta_zmax2
│  │     ├──nslw
│  │     ├──e_linfit_slant
│  │     ├──addpad_flag
│  │     ├──nbin_min
│  │     ├──htspanmin
│  │     ├──alpha_inc
│  │     ├──out_edit_flag
│  │     ├──delta_t_gap_min
│  │     ├──delta_t_lin_fit
│  │     └──r
│  ├──gt1l
│  │  └──signal_find_input
│  │     ├──sig_find_t_inc
│  │     ├──alpha_max
│  │     ├──delta_z_bg
│  │     ├──e_linfit_edit
│  │     ├──e_m
│  │     ├──snrlow
│  │     ├──nslw_v
│  │     ├──nphot_min
│  │     ├──delta_zmin
│  │     ├──delta_t_max
│  │     ├──lslant_flag
│  │     ├──n_delta_z2
│  │     ├──e_m_mult
│  │     ├──delta_t_min
│  │     ├──r2
│  │     ├──snrmed
│  │     ├──n_delta_z1
│  │     ├──min_fit_time_fact
│  │     ├──pc_bckgrd_flag
│  │     ├──t_gap_big
│  │     ├──e_a
│  │     ├──delta_zmax2
│  │     ├──nslw
│  │     ├──e_linfit_slant
│  │     ├──addpad_flag
│  │     ├──nbin_min
│  │     ├──htspanmin
│  │     ├──alpha_inc
│  │     ├──out_edit_flag
│  │     ├──delta_t_gap_min
│  │     ├──delta_t_lin_fit
│  │     └──r
│  ├──altimetry
│  │  ├──atl03_pad
│  │  ├──min_full_sat
│  │  ├──min_near_sat
│  │  ├──min_sat_h
│  │  ├──podppd_pad
│  │  └──band_tol
│  ├──gt3l
│  │  └──signal_find_input
│  │     ├──sig_find_t_inc
│  │     ├──alpha_max
│  │     ├──delta_z_bg
│  │     ├──e_linfit_edit
│  │     ├──e_m
│  │     ├──snrlow
│  │     ├──nslw_v
│  │     ├──nphot_min
│  │     ├──delta_zmin
│  │     ├──delta_t_max
│  │     ├──lslant_flag
│  │     ├──n_delta_z2
│  │     ├──e_m_mult
│  │     ├──delta_t_min
│  │     ├──r2
│  │     ├──snrmed
│  │     ├──n_delta_z1
│  │     ├──min_fit_time_fact
│  │     ├──pc_bckgrd_flag
│  │     ├──t_gap_big
│  │     ├──e_a
│  │     ├──delta_zmax2
│  │     ├──nslw
│  │     ├──e_linfit_slant
│  │     ├──addpad_flag
│  │     ├──nbin_min
│  │     ├──htspanmin
│  │     ├──alpha_inc
│  │     ├──out_edit_flag
│  │     ├──delta_t_gap_min
│  │     ├──delta_t_lin_fit
│  │     └──r
│  ├──gt2l
│  │  └──signal_find_input
│  │     ├──sig_find_t_inc
│  │     ├──alpha_max
│  │     ├──delta_z_bg
│  │     ├──e_linfit_edit
│  │     ├──e_m
│  │     ├──snrlow
│  │     ├──nslw_v
│  │     ├──nphot_min
│  │     ├──delta_zmin
│  │     ├──delta_t_max
│  │     ├──lslant_flag
│  │     ├──n_delta_z2
│  │     ├──e_m_mult
│  │     ├──delta_t_min
│  │     ├──r2
│  │     ├──snrmed
│  │     ├──n_delta_z1
│  │     ├──min_fit_time_fact
│  │     ├──pc_bckgrd_flag
│  │     ├──t_gap_big
│  │     ├──e_a
│  │     ├──delta_zmax2
│  │     ├──nslw
│  │     ├──e_linfit_slant
│  │     ├──addpad_flag
│  │     ├──nbin_min
│  │     ├──htspanmin
│  │     ├──alpha_inc
│  │     ├──out_edit_flag
│  │     ├──delta_t_gap_min
│  │     ├──delta_t_lin_fit
│  │     └──r
│  ├──tep
│  │  ├──ds_gt
│  │  ├──tep_valid_spot
│  │  ├──tep_range_prim
│  │  ├──tep_start_x
│  │  ├──min_tep_secs
│  │  ├──tep_sec_window
│  │  ├──tep_rm_noise
│  │  ├──tep_bin_size
│  │  ├──n_tep_bins
│  │  ├──tep_normalize
│  │  ├──min_tep_ph
│  │  ├──tep_peak_bins
│  │  ├──tep_gap_size
│  │  └──tep_prim_window
│  ├──gt3r
│  │  └──signal_find_input
│  │     ├──sig_find_t_inc
│  │     ├──alpha_max
│  │     ├──delta_z_bg
│  │     ├──e_linfit_edit
│  │     ├──e_m
│  │     ├──snrlow
│  │     ├──nslw_v
│  │     ├──nphot_min
│  │     ├──delta_zmin
│  │     ├──delta_t_max
│  │     ├──lslant_flag
│  │     ├──n_delta_z2
│  │     ├──e_m_mult
│  │     ├──delta_t_min
│  │     ├──r2
│  │     ├──snrmed
│  │     ├──n_delta_z1
│  │     ├──min_fit_time_fact
│  │     ├──pc_bckgrd_flag
│  │     ├──t_gap_big
│  │     ├──e_a
│  │     ├──delta_zmax2
│  │     ├──nslw
│  │     ├──e_linfit_slant
│  │     ├──addpad_flag
│  │     ├──nbin_min
│  │     ├──htspanmin
│  │     ├──alpha_inc
│  │     ├──out_edit_flag
│  │     ├──delta_t_gap_min
│  │     ├──delta_t_lin_fit
│  │     └──r
│  ├──start_delta_time
│  ├──end_geoseg
│  ├──end_region
│  ├──atlas_sdp_gps_epoch
│  ├──end_rgt
│  ├──end_delta_time
│  ├──end_orbit
│  ├──start_cycle
│  ├──start_gpssow
│  ├──end_cycle
│  ├──start_geoseg
│  ├──start_orbit
│  ├──end_gpsweek
│  ├──start_rgt
│  ├──end_gpssow
│  ├──start_region
│  └──start_gpsweek
├──gt3r
│  ├──bckgrd_atlas
│  │  ├──delta_time
│  │  ├──tlm_height_band1
│  │  ├──bckgrd_rate
│  │  ├──tlm_top_band1
│  │  ├──tlm_top_band2
│  │  ├──bckgrd_int_height_reduced
│  │  ├──bckgrd_hist_top
│  │  ├──bckgrd_counts_reduced
│  │  ├──tlm_height_band2
│  │  ├──bckgrd_int_height
│  │  ├──pce_mframe_cnt
│  │  └──bckgrd_counts
│  ├──geolocation
│  │  ├──reference_photon_lat
│  │  ├──delta_time
│  │  ├──range_bias_corr
│  │  ├──neutat_delay_derivative
│  │  ├──reference_photon_lon
│  │  ├──sigma_across
│  │  ├──sigma_lon
│  │  ├──ref_azimuth
│  │  ├──ref_elev
│  │  ├──neutat_ht
│  │  ├──ph_index_beg
│  │  ├──solar_azimuth
│  │  ├──surf_type
│  │  ├──sigma_lat
│  │  ├──tx_pulse_width_lower
│  │  ├──sigma_along
│  │  ├──tx_pulse_skew_est
│  │  ├──tx_pulse_energy
│  │  ├──tx_pulse_width_upper
│  │  ├──sigma_h
│  │  ├──podppd_flag
│  │  ├──velocity_sc
│  │  ├──full_sat_fract
│  │  ├──segment_id
│  │  ├──near_sat_fract
│  │  ├──segment_ph_cnt
│  │  ├──solar_elevation
│  │  ├──bounce_time_offset
│  │  ├──segment_length
│  │  ├──reference_photon_index
│  │  ├──altitude_sc
│  │  ├──segment_dist_x
│  │  └──neutat_delay_total
│  ├──geophys_corr
│  │  ├──delta_time
│  │  ├──dem_flag
│  │  ├──tide_ocean
│  │  ├──tide_earth
│  │  ├──dac
│  │  ├──tide_load
│  │  ├──dem_h
│  │  ├──tide_equilibrium
│  │  ├──geoid
│  │  ├──tide_oc_pole
│  │  └──tide_pole
│  ├──signal_find_output
│  │  ├──sea_ice
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  ├──land_ice
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  ├──land
│  │  │  ├──delta_time
│  │  │  ├──bckgrd_sigma
│  │  │  ├──t_pc_delta
│  │  │  ├──bckgrd_mean
│  │  │  └──z_pc_delta
│  │  └──inlandwater
│  │     ├──delta_time
│  │     ├──bckgrd_sigma
│  │     ├──t_pc_delta
│  │     ├──bckgrd_mean
│  │     └──z_pc_delta
│  └──heights
│     ├──delta_time
│     ├──lat_ph
│     ├──dist_ph_along
│     ├──signal_conf_ph
│     ├──ph_id_pulse
│     ├──h_ph
│     ├──ph_id_channel
│     ├──lon_ph
│     ├──ph_id_count
│     ├──pce_mframe_cnt
│     └──dist_ph_across
├──ds_surf_type
└──ds_xyz

We must note that the same variable names appear in other groups across the file, in the different other Groups.

The DAP4 Protocol makes it easier to identify each variable defined within a Group with a unique Fully Qualyfying Name. In this case, the FQN of each variable, similar to the navigating thgrough file system is:

VarName

FQN_VarName

delta_time

/gt3r/heights/delta_time

lat_ph

/gt3r/heights/lat_ph

lon_ph

/gt3r/heights/lon_ph

With this knowledge, we want to only request these variables from the server’s DMR. The DAP4 specirication for Constraint Expressions is:

\[ \text{Data_url + ?dap4.ce=<FQN_VarName1>;<FQN_VarName2>;<FQN_VarName3> } \]

Let’s try it now:

data_urlCE = data_url+'?dap4.ce=/gt3r/heights/delta_time;/gt3r/heights/lat_ph;/gt3r/heights/lon_ph'
%%time
ds = open_url(data_urlCE, protocol='dap4')
CPU times: user 14.5 ms, sys: 1.36 ms, total: 15.9 ms
Wall time: 253 ms

This is an order of magnitude faster than before!#

Because Groups are NOT part of the DAP2 data model, we cannot illustrate the CE in DAP2 with the ATLAS03 dataset. Instead, we now look at the COADS dataset which has 2D arrays.

Spatial Subsetting#

Continuing to demonstrate CEs in the DAP4 data model, we now want to request only a subset of the variables. We first take a look at the complete dataset

%%time
data_url = 'http://test.opendap.org:8080/opendap/ghrsst/20210102090000-JPL-L4_GHRSST-SSTfnd-MUR-GLOB-v02.0-fv04.1.h5'
CPU times: user 9 μs, sys: 1 μs, total: 10 μs
Wall time: 12.9 μs
%%time
ds = open_url(data_url, protocol='dap4')
CPU times: user 11.9 ms, sys: 1.64 ms, total: 13.6 ms
Wall time: 254 ms
ds.tree()
.20210102090000-JPL-L4_GHRSST-SSTfnd-MUR-GLOB-v02.0-fv04.1.h5
├──time
├──lat
├──lon
├──mask
├──sea_ice_fraction
├──dt_1km_data
├──analysed_sst
├──analysis_error
└──sst_anomaly

Same as before in the DAP4 data model, we have

VarName

FQN_VarName

time

/time

lat

/lat

lon

/lon

mask

/mask

sea_ice_fraction

/sea_ice_fraction

dt_1km_data

/dt_1km_data

analysed_sst

/analysed_sst

analysis_error

/analysis_error

sst_anomaly

/sst_anomaly

ds['analysed_sst'].shape
(1, 17999, 36000)
ds['analysed_sst'].attributes
{'long_name': 'analysed sea surface temperature',
 'standard_name': 'sea_surface_foundation_temperature',
 'units': 'kelvin',
 '_FillValue': -32768,
 'add_offset': 298.15,
 'scale_factor': 0.001,
 'valid_min': -32767,
 'valid_max': 32767,
 'comment': '"Final" version using Multi-Resolution Variational Analysis (MRVA) method for interpolation',
 'coordinates': 'lon lat',
 'source': 'MODIS_T-JPL, MODIS_A-JPL, AMSR2-REMSS, AVHRRMTA_G-NAVO, AVHRRMTB_G-NAVO, iQUAM-NOAA/NESDIS, Ice_Conc-OSISAF',
 'Maps': ('/lon', '/lat', '/time')}
print('Dimensions of variable:', ds['analysed_sst'].dimensions)
Dimensions of variable: ['/time', '/lat', '/lon']
ds.dimensions
{'time': 1, 'lat': 17999, 'lon': 36000}

We see that the variable has three dimensions, and these happen to coincide with those entire dataset.

Spatial Subset#

We have yet to download/retrieve any data. Only the DMR has so far been requested by PyDAP. Consider the scenario where we only want to inspect a spatial subset of the data, defined by the indexes ranges aka hyperslabs.

Say we want to retrieve only the first 100 points of lat, and the last 300 points of lon, of all variables in the dataset. In DAP4, there are two options to accomplish this with the URL.

  1. Traditional Approach. Define the hyperslab for each variable you request. The Data Request Form allows users to (interactively) build such URLS (by selecting boxes and modifying hyperslabs). Following this approach, you get the following Constrained URL

data_url + ?dap4.ce=/time;/lat[0:1:100];/lon[35700:1:];/mask[0][0:1:100][35700:1:];/sea_ice_fraction[0][0:1:100][35700:1:];/dt_1km_data[0][0:1:100][35700:1:];/analysed_sst[0][0:1:100][35700:1:];/analysed_sst[0][0:1:100][35700:1:];/analysis_error[0][0:1:100][35700:1:];/sst_anomaly[0][0:1:100][35700:1:]

Lets try it!

%%time
nds = open_url(data_url+'?dap4.ce=/time[0];/lat[0:1:300];/lon[35699:1:35999];/mask[0][0:1:300][35699:1:35999];/sea_ice_fraction[0][0:1:300][35699:1:35999];/dt_1km_data[0][0:1:300][35699:1:35999];/analysed_sst[0][0:1:300][35699:1:35999];/analysis_error[0][0:1:300][35699:1:35999];/sst_anomaly[0][0:1:300][35699:1:35999]', protocol='dap4')
CPU times: user 10.5 ms, sys: 982 μs, total: 11.5 ms
Wall time: 329 ms
nds
<DatasetType with children 'time', 'lat', 'lon', 'mask', 'sea_ice_fraction', 'dt_1km_data', 'analysed_sst', 'analysis_error', 'sst_anomaly'>
nds['/analysed_sst'].shape
(1, 301, 301)
nds['/lon'].shape
(301,)

The spatial subsetting described above worked fine. It is very verbose and you have to explicitely set the size of all variables, if you want the resulting subset dataset to be self-consistent. For example, it can be easy to define the spatial subset only on a variable and not the rest.

%%time
nds = open_url(data_url+'?dap4.ce=/time;/lat;/lon;/mask;/sea_ice_fraction;/dt_1km_data;/analysed_sst[0][0:1:300][35699:1:35999]', protocol='dap4')
CPU times: user 11.5 ms, sys: 1.36 ms, total: 12.9 ms
Wall time: 342 ms
nds['lat'].shape != nds['analysed_sst'].shape
True
nds['lat'].shape, nds['analysed_sst'].shape
((17999,), (1, 301, 301))

Next we provide an alternative approach that is less error prone, and makes use of Shared Dimensions.

  1. Shared Dimensions: This alternative approach can be used to define the spatial subsetting via the dimensions. The syntax is:

data_url + ?dap4.ce=<FQN_Dim1>=[subset];<FQN_Dim2>=[subset];<FQN_Var1>;<FQN_Var3>;<FQN_Var3>;...<FQN_VarN>

Where <FQN_Var1> may be the same as <FQN_Dim1>.

In the syntax above,

a) The subset is first defined on the dimensions by the = signs. Dimensions may be Global (at the root level), or within a Group.

b) The user then defines the variables ot be included in the request by PyDAP. The subset defined in the previous space will be applied to the variable.

Using the example, the much simplified URL becomes:

%%time
nds = open_url(data_url+"?dap4.ce=/lat=[0:1:300];/lon=[35699:1:35999];/time;/lat;/lon;/mask;/sea_ice_fraction;/dt_1km_data;/analysed_sst;/analysis_error;/sst_anomaly", protocol='dap4')
CPU times: user 14.8 ms, sys: 1.37 ms, total: 16.2 ms
Wall time: 234 ms
nds.tree()
.20210102090000-JPL-L4_GHRSST-SSTfnd-MUR-GLOB-v02.0-fv04.1.h5
├──time
├──lat
├──lon
├──mask
├──sea_ice_fraction
├──dt_1km_data
├──analysed_sst
├──analysis_error
└──sst_anomaly
nds['/analysed_sst'].shape == nds['sst_anomaly'].shape
True