DISP‐S1 Final Acceptance Testing Instructions - nasa/opera-sds-pge GitHub Wiki
This page contains instructions for performing Acceptance Testing for the DISP-S1 Final delivery from the OPERA-ADT team. These instructions pertain to the latest version of the Final release, currently delivery v6.9. These instructions assume the user has access to the JPL Artifactory-FN, and has Docker installed on their local machine.
NOTE: For the current delivery, all checks are expected pass when the AT has been run on an AMD-family instance type.
Acquiring the DISP-S1 CalVal Docker Image
The image is currently hosted on JPL Artifactory-FN, which requires JPL VPN access and JPL credentials. You may also need to be added to the gov.nasa.jpl.opera.adt organization.
Once you have access, the container tarball delivery is available under general/gov/nasa/jpl/opera/adt/disp_s1/r6.9/final/dockerimg_disp_s1_final.tar
. Sample inputs and outputs are also available under general/gov/nasa/jpl/opera/adt/disp_s1/r6.9/final/delivery_data_small.tar
.
Documentation for the current delivery is at general/gov/nasa/jpl/opera/adt/disp_s1/r6.6/final/documents/
.
Download both images to a location on your local machine. This location will be referred to throughout this instructions as <DISP_S1_DIR>
Loading the image into Docker
The first step in running the DISP-S1 image is to load it into Docker via the following command:
docker load -i <DISP_S1_DIR>/dockerimg_disp_s1_final.tar
This should add the Docker image to your local repository with the name opera/disp-s1
and the tag 0.5.9
.
Preparing the test data
Once the delivery_data_small.tar
file is downloaded to your local machine, unpack it to <DISP_S1_DIR>
:
tar -xvf delivery_data_small.tar
mv delivery_data_small/* .
rm -rf delivery_data_small
This will create the following directories within <DISP_S1_DIR>
:
- config_files/
- algorithm_parameters_historical_20250701.yaml
- runconfig_historical.yaml
- dynamic_ancillary_files/
- ionosphere_files/
- static_layers/
- water_mask_0.tif
- water_mask_0.tif.aux.xml (unused by acceptance test)
- water_mask.vrt
- golden_output/
- historical/
- <expected .nc and .png products>
- compressed_slcs/
- historical/
- input_slcs/
- <expected input .h5 products>
- opera-disp-s1-algorithm-parameters-overrides-2025-06-17.json
- static_ancillary_files/
- opera-disp-s1-reference-dates-2025-02-13.json
- opera-s1-disp-0.9.0-frame-to-burst.json.zip
Note there are no runconfigs or golden outputs for the "forward" case in this delivery. There are also no troposphere files or DEM to be used with this release.
In order to execute the SAS, the input file directory, runconfig and an output location will be mounted into the container instance as Docker Volumes. To help streamline this process, we recommend making the following changes within the <DISP_S1_DIR>
directory:
-
Create a directory named
runconfig
just under<DISP_S1_DIR>
, and copy the existing runconfig YAML files into it:mkdir -p <DISP_S1_DIR>/runconfig
cp <DISP_S1_DIR>/config_files/*.yaml <DISP_S1_DIR>/runconfig/
NOTE: There will be 2 sets of runconfig files one historical
and one forward
. These will be used as input for separate runs of the container.
- Update the
algorithm_parameters_file
setting in<DISP_S1_DIR>/runconfig/runconfig_historical.yaml
to point at the version we just copied:
# REQUIRED: Path to file containing SAS algorithm parameters.
# Type: string.
algorithm_parameters_file: runconfig/algorithm_parameters_historical_20250701.yaml
Update thealgorithm_parameters_file
setting inrunconfig_forward.yaml
to point at the version we just copied:
# REQUIRED: Path to file containing SAS algorithm parameters.
# Type: string.
algorithm_parameters_file: runconfig/algorithm_parameters_forward.yaml
Executing the DISP-S1 container on the sample datasets
Running the Forward case (SKIP FOR DELIVERY 6.9)
Change directory into the <DISP_S1_DIR>
directory.
cd <DISP_S1_DIR>/
We're now ready to execute the 'forward' configuration of the DISP-S1 Final delivery. Run the following the command to kick off execution with the test assets:
NOTE: the relative path to the runconfig file must be specified in the docker run command. Assuming you are running from within <DISP_S1_DIR>
, the $(pwd)
command can be utilized as a shortcut.
docker run --rm --user $(id -u):$(id -g) \
--volume $(pwd):/work \
opera/disp-s1:0.5.0 disp-s1 run runconfig/runconfig_forward.yaml
The docker container will output progress messages as it runs, e.g.:
[INFO|displacement|L100] 2024-10-01T16:05:32+0000: Found SLC files from 2 bursts
...
Execution time for the small test case on opera-dev-pge (r6i.2xlarge at time of writing) was about 15 minutes.
When the docker run is finished, scratch/forward/
and output/forward/
directories will be created.
The output/forward directory will contain the product file:
-rw-r--r-- 1 collinss cloud-user 83886080 Oct 1 16:19 20170217_20170430.nc
There will also be a several .png files and a compressed_slcs/
directory:
-rw-r--r-- 1 collinss cloud-user 252733 Oct 1 16:18 20170217_20170430.displacement.png
-rw-r--r-- 1 collinss cloud-user 247842 Oct 1 16:18 20170217_20170430.short_wavelength_displacement.png
drwxr-xr-x 2 collinss cloud-user 134 Oct 1 16:19 compressed_slcs
The compressed_slcs/
directory contains compressed .h5 files:
-rw-r--r-- 1 collinss cloud-user 193776645 Oct 1 16:19 compressed_t027_056725_iw1_20170217_20170217_20170430.h5
-rw-r--r-- 1 collinss cloud-user 193550640 Oct 1 16:19 compressed_t027_056726_iw1_20170217_20170217_20170430.h5
Running the Historical case
Change directory into the DISP_S1_DIR
directory.
cd <DISP_S1_DIR>/
We're now ready to execute the 'historical' DISP-S1 Interface.
Note: the relative path to the runconfig file must be specified in the docker run command
docker run --rm --user $(id -u):$(id -g) \
--volume $(pwd):/work \
opera/disp-s1:0.5.9 disp-s1 run runconfig/runconfig_historical.yaml
The docker container will output progress messages as it runs, e.g.:
[INFO|_masking|L157] 2025-07-01T17:37:06+0000: Extracting layover shadow mask from dynamic_ancillary_files/static_layers/OPERA_L2_CSLC-S1-STATIC_T027-056725-IW1_20140403_S1A_v1.0.h5 to /work/scratch/historical/layover_shadow_masks/layover_shadow_t027_056725_iw1.tif
[INFO|_masking|L157] 2025-07-01T17:37:07+0000: Extracting layover shadow mask from dynamic_ancillary_files/static_layers/OPERA_L2_CSLC-S1-STATIC_T027-056726-IW1_20140403_S1A_v1.0.h5 to /work/scratch/historical/layover_shadow_masks/layover_shadow_t027_056726_iw1.tif
[INFO|displacement|L100] 2025-07-01T17:37:08+0000: Found SLC files from 2 bursts
...
Execution time for the small test case on opera-dev-pge (r6a.4xlarge at time of writing) was about 50 minutes.
NOTE: Due to the increased memory consumption used by DISP-S1 when running in historical mode, R-family instances (such as r6[a|i].4xlarge) are recommended when running this portion of the Acceptance Test. If the test instance needs to be converted to an R-family instance, contact an OPERA PGE developer. Also note that for the purpose of the Quality Assurance test, an AMD-based instance type should be utilized.
When the docker run is finished, scratch/historical/
and output/historical/
directories will be created.
The output/historical directory will contain the following product files:
output/historical/
├── 20170217_20170301.nc
├── 20170217_20170301.short_wavelength_displacement.png
├── 20170217_20170313.nc
├── 20170217_20170313.short_wavelength_displacement.png
├── 20170217_20170325.nc
├── 20170217_20170325.short_wavelength_displacement.png
├── 20170217_20170406.nc
├── 20170217_20170406.short_wavelength_displacement.png
├── 20170217_20170418.nc
├── 20170217_20170418.short_wavelength_displacement.png
├── 20170217_20170430.nc
├── 20170217_20170430.short_wavelength_displacement.png
└── compressed_slcs
├── compressed_t027_056725_iw1_20170430_20170217_20170430.h5
└── compressed_t027_056726_iw1_20170430_20170217_20170430.h5
Running the Quality Assurance test
Now that we've successfully executed the SAS container and generated outputs, the last step is to perform a QA check against the expected outputs.
A Python program to compare DISP-S1 products generated by DISP-S1-SAS with expected outputs “golden datasets” is included in the Docker image. The disp-s1 application can run a "validate" workflow that accepts two input files: the golden dataset and the test dataset.
The docker command to run this is:
docker run --rm --volume $(pwd):/work \
opera/disp-s1:0.5.9 \
disp-s1 validate <path to golden dataset> <path to output dataset>
For example, if the SAS was run using the example command above and the result is in the output/ directory, the validation program can be run as as follows:
docker run --rm --volume $(pwd):/work \
opera/disp-s1:0.5.9 \
disp-s1 validate golden_output/forward/20170217_20170430.nc output/forward/20170217_20170430.nc
for f in `find golden_output/historical/ -type f -iname '*.nc' | sed 's|^.*/||'`; do docker run --rm --volume $(pwd):/work opera/disp-s1:0.5.9 disp-s1 validate golden_output/historical/$f output/historical/$f; done
Sample output from comparison of Historical mode products:
for f in `find golden_output/historical/ -type f -iname '*.nc' | sed 's|^.*/||'`; do docker run --rm --volume $(pwd):/work opera/disp-s1:0.5.7 disp-s1 validate golden_output/historical/$f output/historical/$f; done
[INFO|validate|L503] 2025-07-01T18:58:14+0000: Comparing HDF5 contents...
[INFO|validate|L286] 2025-07-01T18:58:14+0000: Checking displacement...
[INFO|validate|L337] 2025-07-01T18:58:19+0000: Test nan count: 0/3610477 (0.000%)
[INFO|validate|L338] 2025-07-01T18:58:19+0000: Reference nan count: 0/3610477 (0.000%)
[INFO|validate|L366] 2025-07-01T18:58:23+0000: Mean absolute re-wrapped phase error: 0.00000 rad
[INFO|validate|L367] 2025-07-01T18:58:23+0000: Max absolute re-wrapped phase error: 0.00000 rad
[INFO|validate|L371] 2025-07-01T18:58:23+0000: Non-congruent pixel count: 0/3610477 (0.000%)
[INFO|validate|L195] 2025-07-01T18:58:25+0000: Checking connected component labels...
[INFO|validate|L226] 2025-07-01T18:58:26+0000: Test unwrapped area: 3610477/69037976 (5.230%)
[INFO|validate|L227] 2025-07-01T18:58:26+0000: Reference unwrapped area: 3610477/69037976 (5.230%)
[INFO|validate|L228] 2025-07-01T18:58:26+0000: Intersection/Reference: 3610477/3610477 (100.000%)
[INFO|validate|L229] 2025-07-01T18:58:26+0000: Intersection/Union: 3610477/3610477 (100.000%)
[INFO|validate|L415] 2025-07-01T18:58:43+0000: /identification/product_version: b'1.1' vs. b'1.1'
[INFO|validate|L415] 2025-07-01T18:58:43+0000: /identification/processing_start_datetime: b'2025-07-01 15:27:49' vs. b'2025-07-01 17:37:04'
[INFO|validate|L415] 2025-07-01T18:58:43+0000: /metadata/disp_s1_software_version: b'0.5.9' vs. b'0.5.9'
[INFO|validate|L415] 2025-07-01T18:58:43+0000: /metadata/dolphin_software_version: b'0.40.0' vs. b'0.40.0'
[INFO|validate|L415] 2025-07-01T18:58:43+0000: /metadata/pge_runconfig: b"input_file_group:\n # REQUIRED: list of paths to CSLC files.\n # Type: array.\n cslc_file_list:\n - input_slcs/OPERA_L2_CSLC-S1_T027-056725-IW1_20170217T132750Z_20240625T060850Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056726-IW1_20170217T132752Z_20240625T060850Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056725-IW1_20170301T132749Z_20240625T090210Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056726-IW1_20170301T132752Z_20240625T090210Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056725-IW1_20170313T132750Z_20240625T121542Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056726-IW1_20170313T132753Z_20240625T121542Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056725-IW1_20170325T132750Z_20240625T163704Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056726-IW1_20170325T132753Z_20240625T163704Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056725-IW1_20170406T132750Z_20240625T225442Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056726-IW1_20170406T132753Z_20240625T225442Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056725-IW1_20170418T132751Z_20240626T003055Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056726-IW1_20170418T132754Z_20240626T003055Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056725-IW1_20170430T132752Z_20240626T015700Z_S1A_VV_v1.1.h5\n - input_slcs/OPERA_L2_CSLC-S1_T027-056726-IW1_20170430T132754Z_20240626T015700Z_S1A_VV_v1.1.h5\n # REQUIRED: Frame ID of the bursts contained in `cslc_file_list`.\n # Type: integer.\n frame_id: 7091\n # (For FORWARD/'Catch up' HISTORICAL processing mode) last processed date for the frame. If\n # provided, the SAS will only output products whose secondary datetime is *after*\n # `last_processed`. Otherwise, the SAS will output all products.\n # Type: string | null.\n last_processed:\ndynamic_ancillary_file_group:\n # REQUIRED: Path to file containing SAS algorithm parameters.\n # Type: string.\n algorithm_parameters_file: \n config_files/algorithm_parameters_historical_20250701.yaml\n # Paths to the CSLC static_layer files (1 per burst) with line-of-sight unit vectors. If\n # none provided, corrections using CSLC static_layer are skipped.\n # Type: array.\n static_layers_files:\n - dynamic_ancillary_files/static_layers/OPERA_L2_CSLC-S1-STATIC_T027-056725-IW1_20140403_S1A_v1.0.h5\n - dynamic_ancillary_files/static_layers/OPERA_L2_CSLC-S1-STATIC_T027-056726-IW1_20140403_S1A_v1.0.h5\n # Optional Byte mask file used to ignore low correlation/bad data (e.g water mask).\n # Convention is 0 for no data/invalid, and 1 for good data. Dtype must be uint8.\n # Type: string | null.\n mask_file: dynamic_ancillary_files/water_mask.vrt\n # Path to the DEM file covering full frame. If none provided, corrections using DEM are\n # skipped.\n # Type: string | null.\n dem_file:\n # List of paths to TEC files (1 per date) in IONEX format for ionosphere correction. If none\n # provided, ionosphere corrections are skipped.\n # Type: array | null.\n
...skipping...
s_cost_type: constant\n # Scale factor used to compute edge costs for spatial unwrapping.\n # Type: number.\n s_cost_scale: 100.0\n # Number of tiles to process in parallel. Set to 0 for all tiles.\n # Type: integer.\n num_parallel_tiles: 1\n merger_settings:\n # Minimum number of overlap pixels to be considered valid.\n # Type: integer.\n min_overlap_points: 25\n # Currently, only 'dirichlet' is supported.\n # Type: dirichlet.\n method: dirichlet\n # Method used to estimate bulk offset between tiles.\n # Type: string.\n # Options: ['integer', 'L2'].\n bulk_method: L2\n # Number of interferograms to merge in one batch. Use zero to merge all interferograms in a\n # single batch.\n # Type: integer.\n num_parallel_ifgs: 21\ntimeseries_options:\n # Whether to run the inversion step after unwrapping, if more than a single-reference\n # network is used.\n # Type: boolean.\n run_inversion: true\n # Norm to use during timeseries inversion.\n # Type: string.\n # Options: ['L1', 'L2'].\n method: L1\n # Reference point (row, col) used if performing a time series inversion. If not provided, a\n # point will be selected from a consistent connected component with low amplitude\n # dispersion.\n # Type: array | null.\n reference_point:\n # Run the velocity estimation from the phase time series.\n # Type: boolean.\n run_velocity: false\n # Pixels with correlation below this value will be masked out.\n # Type: number.\n correlation_threshold: 0.0\n # Size (rows, columns) of blocks of data to load at a time. 3D dimsion is number of\n # interferograms (during inversion) and number of SLC dates (during velocity fitting).\n # Type: array.\n block_shape:\n - 256\n - 256\n # Number of parallel blocks to process at once.\n # Type: integer.\n num_parallel_blocks: 4\ncorrection_options:\n ionosphere_files:\n - dynamic_ancillary_files/ionosphere_files/jplg0070.18i\n - dynamic_ancillary_files/ionosphere_files/jplg0190.18i\n - dynamic_ancillary_files/ionosphere_files/jplg0310.18i\n - dynamic_ancillary_files/ionosphere_files/jplg0430.18i\n - dynamic_ancillary_files/ionosphere_files/jplg0480.17i\n - dynamic_ancillary_files/ionosphere_files/jplg0550.18i\n - dynamic_ancillary_files/ionosphere_files/jplg0600.17i\n - dynamic_ancillary_files/ionosphere_files/jplg0670.18i\n - dynamic_ancillary_files/ionosphere_files/jplg0720.17i\n - dynamic_ancillary_files/ionosphere_files/jplg0790.18i\n - dynamic_ancillary_files/ionosphere_files/jplg0840.17i\n - dynamic_ancillary_files/ionosphere_files/jplg0910.18i\n - dynamic_ancillary_files/ionosphere_files/jplg0960.17i\n - dynamic_ancillary_files/ionosphere_files/jplg1030.18i\n - dynamic_ancillary_files/ionosphere_files/jplg1080.17i\n - dynamic_ancillary_files/ionosphere_files/jplg1150.18i\n - dynamic_ancillary_files/ionosphere_files/jplg1200.17i\n - dynamic_ancillary_files/ionosphere_files/jplg1270.18i\n - dynamic_ancillary_files/ionosphere_files/jplg1320.17i\n - dynamic_ancillary_files/ionosphere_files/jplg1390.18i\n - dynamic_ancillary_files/ionosphere_files/jplg1440.17i\n - dynamic_ancillary_files/ionosphere_files/jplg1510.18i\n - dynamic_ancillary_files/ionosphere_files/jplg1560.17i\n - dynamic_ancillary_files/ionosphere_files/jplg1630.18i\n - dynamic_ancillary_files/ionosphere_files/jplg1750.18i\n - dynamic_ancillary_files/ionosphere_files/jplg1800.17i\n - dynamic_ancillary_files/ionosphere_files/jplg1870.18i\n - dynamic_ancillary_files/ionosphere_files/jplg1920.17i\n - dynamic_ancillary_files/ionosphere_files/jplg1990.18i\n - dynamic_ancillary_files/ionosphere_files/jplg2040.17i\n - dynamic_ancillary_files/ionosphere_files/jplg2110.18i\n - dynamic_ancillary_files/ionosphere_files/jplg2160.17i\n - dynamic_ancillary_files/ionosphere_files/jplg2280.17i\n - dynamic_ancillary_files/ionosphere_files/jplg2400.17i\n - dynamic_ancillary_files/ionosphere_files/jplg2520.17i\n - dynamic_ancillary_files/ionosphere_files/jplg2640.17i\n - dynamic_ancillary_files/ionosphere_files/jplg2760.17i\n - dynamic_ancillary_files/ionosphere_files/jplg2880.17i\n - dynamic_ancillary_files/ionosphere_files/jplg3000.17i\n - dynamic_ancillary_files/ionosphere_files/jplg3120.17i\n - dynamic_ancillary_files/ionosphere_files/jplg3190.18i\n - dynamic_ancillary_files/ionosphere_files/jplg3240.17i\n - dynamic_ancillary_files/ionosphere_files/jplg3360.17i\n - dynamic_ancillary_files/ionosphere_files/jplg3480.17i\n - dynamic_ancillary_files/ionosphere_files/jplg3600.17i\n geometry_files:\n - dynamic_ancillary_files/static_layers/OPERA_L2_CSLC-S1-STATIC_T027-056725-IW1_20140403_S1A_v1.0.h5\n - dynamic_ancillary_files/static_layers/OPERA_L2_CSLC-S1-STATIC_T027-056726-IW1_20140403_S1A_v1.0.h5\n dem_file:\nrecommended_temporal_coherence_threshold: 0.6\nrecommended_similarity_threshold: 0.4\nrecommended_use_conncomp: false\nspatial_wavelength_cutoff: 30000.0\nbrowse_image_vmin_vmax:\n - -0.05\n - 0.05\nnum_parallel_products: 4\n"
[INFO|validate|L415] 2025-07-01T18:58:44+0000: /metadata/source_data_software_COMPASS_version: b'0.5.5' vs. b'0.5.5'
[INFO|validate|L415] 2025-07-01T18:58:44+0000: /metadata/source_data_software_ISCE3_version: b'0.15.1' vs. b'0.15.1'
[INFO|validate|L415] 2025-07-01T18:58:44+0000: /metadata/source_data_software_s1_reader_version: b'0.2.4' vs. b'0.2.4'
[INFO|validate|L507] 2025-07-01T18:58:44+0000: Checking geospatial metadata...
[INFO|validate|L513] 2025-07-01T18:58:44+0000: Files golden_output/historical/20170217_20170430.nc and output/historical/20170217_20170430.nc match.
For the current delivery, all checks are expected pass when the AT has been run on an AMD-family instance type.