1. Overview
This document describes the HDF5 data format (Version 2.0) for the EarthScope/UNAVCO community-contributed InSAR data archive. The format supports interferograms from multiple tracks/platforms within a single HDF5 file, with comprehensive metadata standards for each track. See the introduction of HDF5 for InSAR Products for more context. Contact support for questions or help.
Key Features of Version 2.0:
- Simplified Structure: no GEOCODE group (interferograms of different tracks/platforms are directly under root)
- Multi-Track Support: Store multiple interferograms from different platforms/orbits in a single file
- Independent Geometries: Each track has its own view geometries (e.g., LOS vectors) and acquisition parameters
- Hierarchical Organization: Root ā Track ā Interferograms or Time Series
- Multi-Platform Fusion: Combine data from different sensors (ALOS-2, Sentinel-1, etc.)
- Clear Metadata Separation: File-wide processing vs. track-specific acquisition metadata
- Flexible Product Types: Support for interferograms, displacement time series, and velocity maps
Common Use Cases:
- Single-Track Interferogram Archive: Store multiple interferometric pairs from one satellite track, including wrapped/unwrapped phase, coherence, and LOS geometry. Ideal for earthquake or landslide studies from a single viewing geometry.
- Multi-Track Event Analysis: Combine interferograms from different platforms and/or view geometries to resolve 3D surface deformation. Essential for volcanic deformation, large earthquakes, or subsidence monitoring where multiple viewing angles improve deformation characterization.
- Multi-Platform Fusion: Integrate data from different sensors (e.g., ALOS-2 L-band + Sentinel-1 C-band) to leverage different penetration depths and temporal sampling. Useful for vegetated areas or rapid deformation events.
- Time Series Products: Store cumulative displacement time series or average velocity maps in LOS direction. Each track maintains its own LOS geometry for proper interpretation. Commonly used for long-term ground motion monitoring.
- Regional Deformation Mosaics: Combine multiple adjacent tracks covering a large spatial extent (e.g., entire plate boundaries, large volcanic systems). Each track preserves independent processing parameters and quality metrics.
- Comparative Studies: Archive interferograms from the same area but different time periods, processing methods, or atmospheric corrections. Facilitates method comparison and reprocessing validation.
- Data Publication and Archiving: Distribute processed InSAR products with comprehensive metadata for reproducibility. Include processing software versions, DEM sources, and atmospheric corrections alongside the data products.
2. File Structure
2.1 Structure for INTERFEROGRAM Products
2.2 Structure for DISP. TIME SERIES Products
2.3 Structure for LOS_VELOCITY Products
2.4 Track Naming Convention
Format: {PLATFORM}_{ORBIT}_{DIRECTION}
Examples:
ALOS2_073_A- ALOS-2, orbit 73, ascendingS1_064_D- Sentinel-1, orbit 64, descendingTSX_142_A- TerraSAR-X, orbit 142, ascendingCSK_037_D- COSMO-SkyMed, orbit 37, descending
Alternative (if needed): {PLATFORM}_{ORBIT}_{DIRECTION}_{SWATH}
3. Root-Level Metadata (File-Wide)
These metadata fields apply to the entire file and describe processing methods used across all tracks.
| Attribute | Type | Description | Example |
|---|---|---|---|
| processing_type REQUIRED | String | Type of InSAR product | "INTERFEROGRAM", "LOS_VELOCITY", "DISP. TIME SERIES" |
| processing_software REQUIRED | String | Software name and version used | "ISCE2 v2.6.3 + SNAPHU v2.0.5" |
| history REQUIRED | String | File creation timestamp (ISO 8601) | "2024-01-15T10:30:00" |
| sign_convention REQUIRED | String | Sign convention of LOS displacement/velocity | "Positive LOS displacement corresponds to surface motion toward the sensor" |
| creators RECOMMENDED | String (JSON) | JSON array of author objects | '[{"name":"Jane Smith","institution":"Univ"}]' |
| publication RECOMMENDED | String | Related publication citation with DOI | "Smith et al. (2024). doi:10.xxxx/yyyy" |
4. Track-Level Metadata
These metadata fields are stored as attributes on each track group (e.g., /ALOS2_073_A/) and describe the acquisition parameters specific to that track.
| Attribute | Type | Description | Example |
|---|---|---|---|
| platform REQUIRED | String | Name of the platform/mission | "ALOS-2", "SENTINEL-1", see supported platforms |
| relative_orbit REQUIRED | Integer | Relative orbit/track/path number | 73, 154 |
| flight_direction REQUIRED | String | Flight direction | "A" (Ascending) or "D" (Descending) |
| look_direction REQUIRED | String | Look direction | "R" (Right) or "L" (Left) |
| beam_mode REQUIRED | String | Beam mode as used by space agency | "WD1", "IW", "SM" |
| beam_swath REQUIRED | String | Swath identifier (no spaces) | "W1", "IW2", "strip_013", "NA" if unknown |
| wavelength REQUIRED | Float | Radar wavelength (meters) | 0.0555462 (C-band), 0.236 (L-band) |
| scene_footprint REQUIRED | String | WKT POLYGON of scene extent (lon, lat) | "POLYGON((-118.2 34.0, ...))" |
| first_date REQUIRED | String | Earliest acquisition date of the track (ISO 8601: YYYY-MM-DD) | "2024-01-01" |
| last_date REQUIRED | String | Latest acquisition date of the track (ISO 8601: YYYY-MM-DD) | "2024-03-01" |
| time_acquisition REQUIRED | String | Approximate time (UTC) of image acquisition over the study area | "18:03" |
| polarization RECOMMENDED | String | Polarization mode | "VV", "HH", "VV+VH" |
| frame RECOMMENDED | Integer | Frame number | 1234 |
| atmos_correct_method RECOMMENDED | String | Atmospheric correction method | "GACOS", "ERA5", "None" |
| processing_dem RECOMMENDED | String | DEM source used for processing | "SRTM30", "ASTER" |
| post_processing_method RECOMMENDED | String | Post-processing approach | "MintPy", "StaMPS", "NSBAS" |
| percent_unwrapped RECOMMENDED | Float | Average % unwrapped pixels (track-wide) | 92.5 |
| average_coherence RECOMMENDED | Float | Average coherence (track-wide) | 0.68 |
| reference_date REQUIRED for TIME SERIES | String | Reference date for this track's time series (applicable for DISP. TIME SERIES product). Overrides root-level reference_date if present | "20240101" |
5. Interferogram-Specific Metadata
These metadata fields are stored as attributes on each date-pair group (e.g., /ALOS2_073_A/20240101_20240113/) for INTERFEROGRAM products only:
| Attribute | Type | Description | Example |
|---|---|---|---|
| reference_date RECOMMENDED | String | Reference (first) acquisition date (YYYYMMDD) | "20240101" |
| secondary_date RECOMMENDED | String | Secondary (repeat) acquisition date (YYYYMMDD) | "20240113" |
| temporal_baseline_days RECOMMENDED | Integer | Temporal baseline in days | 12 |
| baseline_perp RECOMMENDED | Float | Perpendicular baseline (meters) | 45.2 |
| reference_platform RECOMMENDED | String | Reference image platform/satellite | "SENTINEL-1A" |
| repeat_platform RECOMMENDED | String | Repeat image platform/satellite | "SENTINEL-1B" |
| phase_sign_convention RECOMMENDED | String | Sign convention of phase | "Postive phase corresponds to range increase (i.e., motion away from the platform)" |
| percent_unwrapped RECOMMENDED | Float | Percentage of unwrapped pixels for this interferogram | 94.2 |
| average_coherence RECOMMENDED | Float | Average coherence for this interferogram | 0.72 |
6. Dataset Definitions
Dataset Organization by Processing Type:
- INTERFEROGRAM: Date-pair groups (e.g.,
20240101_20240113/) containing unwrapped/wrapped phase and coherence - DISP. TIME SERIES: Individual displacement datasets (e.g.,
dLOS_20240101) directly under each track - LOS_VELOCITY: Single velocity dataset (
velocity) per track with optional uncertainty fields
6.1 Line-of-Sight (LOS) Vectors (Track-Specific)
Location: /{TRACK}/line_of_sight_{e,n,u} (each track has its own)
Data Type: Float32 or Float64
Components:
line_of_sight_e- East componentline_of_sight_n- North componentline_of_sight_u- Up component
Units: Dimensionless (unit vectors)
Valid Range: [0.0, 1.0] for each component
Note: Each track has independent LOS vectors since acquisition geometry differs between tracks.
6.2 Unwrapped Interferogram (INTERFEROGRAM products only)
Location: /{TRACK}/YYYYMMDD_YYYYMMDD/unwrapped_interferogram
Data Type: Float32 or Float64
Units: Radians
Convention: Positive = increase in range (away from sensor), Negative = decrease in range (towards sensor)
Attributes:
@description- "Unwrapped interferometric phase"@units- "radians"@unwrap_method- Method used (e.g., "SNAPHU")
6.3 Wrapped Interferogram (INTERFEROGRAM products only)
Location: /{TRACK}/YYYYMMDD_YYYYMMDD/wrapped_interferogram
Data Type: Float32 or Float64
Units: Radians
Valid Range: [-Ļ, +Ļ]
Attributes:
@description- "Wrapped interferometric phase"@units- "radians"@valid_range- [-3.14159, 3.14159]
6.4 Correlation (Coherence) (INTERFEROGRAM products only)
Location: /{TRACK}/YYYYMMDD_YYYYMMDD/correlation
Data Type: Float32 or Float64
Units: Dimensionless
Valid Range: [0.0, 1.0]
Interpretation: 0 = pure noise, 1 = perfect correlation
Attributes:
@description- "Interferometric coherence"@units- "dimensionless"@valid_range- [0.0, 1.0]@max_coherence- Maximum coherence observed
6.5 LOS Displacement Time Series (DISP. TIME SERIES products only)
Location: /{TRACK}/dLOS_YYYYMMDD
Naming Convention: dLOS_{date} where date is in YYYYMMDD format
Data Type: Float32 or Float64
Units: Meters (m)
Convention: Positive = motion toward sensor (range decrease), Negative = motion away from sensor (range increase)
Reference: All displacements are relative to the reference date specified in track-level @reference_date (or root-level if track-level not present)
Attributes:
@description- "Cumulative LOS displacement relative to reference date"@units- "meters"@acquisition_date- Date of this acquisition (YYYYMMDD)@reference_date- Reference date for this dataset (YYYYMMDD) - should match track-level reference_date@temporal_coherence(optional) - Average temporal coherence for this date
Important Notes:
- Track-specific reference dates: Each track MUST have its own
@reference_dateattribute. Different tracks can have different reference dates - The reference date dataset (e.g.,
dLOS_20240101) should contain all zeros - Each subsequent date contains cumulative displacement since that track's reference date
- Root-level
@reference_dateis optional and can be used if all tracks share the same reference - Datasets are stored directly under the track group, not in date-pair subgroups
- Time series processing typically uses SBAS, PS, or similar methods
6.6 LOS Velocity (LOS_VELOCITY products only)
Location: /{TRACK}/velocity
Data Type: Float32 or Float64
Units: Meters per year (m/year) or millimeters per year (mm/year)
Convention: Positive = motion toward sensor, Negative = motion away from sensor
Attributes:
@description- "Mean LOS velocity"@units- "m/year" or "mm/year"@time_span_start- Start date of velocity estimation (YYYY-MM-DD)@time_span_end- End date of velocity estimation (YYYY-MM-DD)@estimation_method- Method used (e.g., "linear regression", "MSBAS")
Optional Uncertainty Field: /{TRACK}/velocity_std
- Same dimensions and units as velocity
- Contains standard deviation or uncertainty estimate
@description- "Standard deviation of LOS velocity"
Key Differences Between Product Types:
| Feature | INTERFEROGRAM | DISP. TIME SERIES | LOS_VELOCITY |
|---|---|---|---|
| Data Organization | Date-pair groups | Individual date datasets | Single velocity dataset |
| Dataset Names | YYYYMMDD_YYYYMMDD/ | dLOS_YYYYMMDD | velocity |
| Units | Radians | Meters (m) | m/year or mm/year |
| Reference Date | Not applicable | Required (track-level) | Time span in attributes |
| Typical Use | Raw phase measurements | Time-dependent deformation | Long-term rates |
7. Code Examples
š About These Examples
The following code examples are demonstrations of the file format structure. They use synthetic data to illustrate the organization and metadata requirements.
To use these examples with your data:
- Replace the synthetic data generation sections with your actual interferogram, displacement, or velocity arrays
- Update all metadata fields (platform, orbit, dates, etc.) to match your processing
- Adjust array dimensions to match your data size
- Add additional tracks or dates as needed
7.1 Python Examples
7.1.1 Creating an INTERFEROGRAM File
This example demonstrates the structure for interferogram products. Replace the synthetic data with your actual unwrapped/wrapped phase and coherence arrays.
#!/usr/bin/env python3
"""
Example: Creating an Interferogram HDF5 File (Version 2.0)
Demonstrates the file structure - replace synthetic data with your actual interferograms
"""
import h5py
import numpy as np
from datetime import datetime
# Output filename
filename = 'example_interferogram.h5'
with h5py.File(filename, 'w') as f:
# ============================================================
# 1. ROOT-LEVEL METADATA (file-wide)
# ============================================================
f.attrs['processing_type'] = 'INTERFEROGRAM'
f.attrs['processing_software'] = 'ISCE2 v2.6.3 + SNAPHU v2.0.5'
f.attrs['history'] = datetime.now().isoformat()
f.attrs['sign_convention'] = 'Positive LOS displacement corresponds to surface motion toward the sensor'
# ============================================================
# 2. CREATE TRACK
# ============================================================
track = f.create_group('ALOS2_073_A')
# Track-level metadata (REQUIRED fields)
track.attrs['platform'] = 'ALOS-2'
track.attrs['relative_orbit'] = 73
track.attrs['flight_direction'] = 'A'
track.attrs['look_direction'] = 'R'
track.attrs['beam_mode'] = 'WD1'
track.attrs['beam_swath'] = 'W1'
track.attrs['wavelength'] = 0.236
track.attrs['scene_footprint'] = 'POLYGON((-118.5 34.0, -118.0 34.0, -118.0 34.5, -118.5 34.5, -118.5 34.0))'
track.attrs['first_date'] = '2024-01-01'
track.attrs['last_date'] = '2024-02-08'
track.attrs['time_acquisition'] = '10:23'
# Optional but recommended
track.attrs['polarization'] = 'VV'
# ============================================================
# 3. LOS VECTORS (replace with your actual LOS geometry)
# ============================================================
# TODO: Replace this synthetic data with your actual LOS vectors
demo_shape = (1000, 1200) # Replace with your data dimensions
# Generate synthetic LOS vectors for demonstration
los_e_data = np.random.uniform(0.35, 0.45, demo_shape).astype(np.float32)
los_n_data = np.random.uniform(-0.05, 0.05, demo_shape).astype(np.float32)
los_u_data = np.random.uniform(0.75, 0.85, demo_shape).astype(np.float32)
# Normalize to unit vectors
magnitude = np.sqrt(los_e_data**2 + los_n_data**2 + los_u_data**2)
los_e_data /= magnitude
los_n_data /= magnitude
los_u_data /= magnitude
# Write LOS datasets with compression
los_e = track.create_dataset('line_of_sight_e', data=los_e_data, compression='gzip')
los_e.attrs['description'] = 'LOS unit vector - East component'
los_e.attrs['units'] = 'dimensionless'
los_n = track.create_dataset('line_of_sight_n', data=los_n_data, compression='gzip')
los_n.attrs['description'] = 'LOS unit vector - North component'
los_n.attrs['units'] = 'dimensionless'
los_u = track.create_dataset('line_of_sight_u', data=los_u_data, compression='gzip')
los_u.attrs['description'] = 'LOS unit vector - Up component'
los_u.attrs['units'] = 'dimensionless'
# ============================================================
# 4. INTERFEROGRAM DATA (replace with your actual phase data)
# ============================================================
# Create date-pair group
date_group = track.create_group('20240101_20240113')
# Interferogram metadata
date_group.attrs['reference_date'] = '20240101'
date_group.attrs['secondary_date'] = '20240113'
date_group.attrs['temporal_baseline_days'] = 12
date_group.attrs['baseline_perp'] = 45.2
# TODO: Replace this synthetic data with your actual unwrapped phase
# Generate synthetic unwrapped interferogram for demonstration
x = np.linspace(0, 4*np.pi, demo_shape[1])
y = np.linspace(0, 4*np.pi, demo_shape[0])
X, Y = np.meshgrid(x, y)
unwrapped_data = (np.sin(X/3) * np.cos(Y/3) * 2 * np.pi).astype(np.float32)
# Write unwrapped interferogram
unwrapped = date_group.create_dataset('unwrapped_interferogram',
data=unwrapped_data, compression='gzip')
unwrapped.attrs['description'] = 'Unwrapped interferometric phase'
unwrapped.attrs['units'] = 'radians'
unwrapped.attrs['unwrap_method'] = 'SNAPHU'
# Create wrapped interferogram
wrapped_data = np.angle(np.exp(1j * unwrapped_data)).astype(np.float32)
wrapped = date_group.create_dataset('wrapped_interferogram',
data=wrapped_data, compression='gzip')
wrapped.attrs['description'] = 'Wrapped interferometric phase'
wrapped.attrs['units'] = 'radians'
# TODO: Replace with your actual coherence data
# Generate synthetic coherence for demonstration
corr_data = np.random.uniform(0.5, 0.9, demo_shape).astype(np.float32)
correlation = date_group.create_dataset('correlation',
data=corr_data, compression='gzip')
correlation.attrs['description'] = 'Interferometric coherence'
correlation.attrs['units'] = 'dimensionless'
print(f"ā Created {filename}")
print(f" Explore with: h5ls -r {filename}")
print(f"\nNOTE: This file contains synthetic demo data.")
print("Replace the data generation sections with your actual interferogram data.")
7.1.2 Creating a TIME SERIES File
This example demonstrates the structure for displacement time series products. Replace the synthetic displacement with your actual time series results.
#!/usr/bin/env python3
"""
Example: Creating a Time Series HDF5 File (Version 2.0)
Demonstrates the file structure - replace synthetic data with your actual time series
"""
import h5py
import numpy as np
from datetime import datetime
# Output filename
filename = 'example_timeseries.h5'
with h5py.File(filename, 'w') as f:
# ============================================================
# 1. ROOT-LEVEL METADATA (file-wide)
# ============================================================
f.attrs['processing_type'] = 'DISP. TIME SERIES'
f.attrs['processing_software'] = 'MintPy v1.5.1'
f.attrs['history'] = datetime.now().isoformat()
f.attrs['sign_convention'] = 'Positive LOS displacement corresponds to surface motion toward the sensor'
# ============================================================
# 2. CREATE TRACK
# ============================================================
track = f.create_group('ALOS2_073_A')
# Track-level metadata (REQUIRED fields)
track.attrs['platform'] = 'ALOS-2'
track.attrs['relative_orbit'] = 73
track.attrs['flight_direction'] = 'A'
track.attrs['look_direction'] = 'R'
track.attrs['beam_mode'] = 'WD1'
track.attrs['beam_swath'] = 'W1'
track.attrs['wavelength'] = 0.236
track.attrs['scene_footprint'] = 'POLYGON((-118.5 34.0, -118.0 34.0, -118.0 34.5, -118.5 34.5, -118.5 34.0))'
track.attrs['first_date'] = '2024-01-01'
track.attrs['last_date'] = '2024-04-01'
track.attrs['time_acquisition'] = '10:23'
track.attrs['polarization'] = 'VV'
# REQUIRED for time series: track-specific reference date
track.attrs['reference_date'] = '20240101'
# ============================================================
# 3. LOS VECTORS (replace with your actual LOS geometry)
# ============================================================
# TODO: Replace with your actual LOS vectors
demo_shape = (1000, 1200) # Replace with your data dimensions
los_e_data = np.random.uniform(0.35, 0.45, demo_shape).astype(np.float32)
los_n_data = np.random.uniform(-0.05, 0.05, demo_shape).astype(np.float32)
los_u_data = np.random.uniform(0.75, 0.85, demo_shape).astype(np.float32)
magnitude = np.sqrt(los_e_data**2 + los_n_data**2 + los_u_data**2)
los_e_data /= magnitude
los_n_data /= magnitude
los_u_data /= magnitude
los_e = track.create_dataset('line_of_sight_e', data=los_e_data,
compression='gzip', compression_opts=6)
los_e.attrs['description'] = 'LOS unit vector - East component'
los_e.attrs['units'] = 'dimensionless'
los_n = track.create_dataset('line_of_sight_n', data=los_n_data,
compression='gzip', compression_opts=6)
los_n.attrs['description'] = 'LOS unit vector - North component'
los_n.attrs['units'] = 'dimensionless'
los_u = track.create_dataset('line_of_sight_u', data=los_u_data,
compression='gzip', compression_opts=6)
los_u.attrs['description'] = 'LOS unit vector - Up component'
los_u.attrs['units'] = 'dimensionless'
# ============================================================
# 4. DISPLACEMENT TIME SERIES (replace with your actual displacements)
# ============================================================
# List of dates in your time series
dates = ['20240101', '20240113', '20240125', '20240208']
print(f"Creating time series with {len(dates)} dates...")
for idx, date_str in enumerate(dates):
# TODO: Replace this synthetic data with your actual displacement
if idx == 0:
# Reference date: all zeros
disp_data = np.zeros(demo_shape, dtype=np.float32)
else:
# Cumulative displacement in meters
# This is synthetic - replace with your actual time series data
disp_data = (np.random.randn(*demo_shape) * 0.01 * idx).astype(np.float32)
# Create dataset: dLOS_YYYYMMDD (note: directly under track, not in subgroups)
dataset_name = f'dLOS_{date_str}'
dset = track.create_dataset(dataset_name, data=disp_data,
compression='gzip', compression_opts=6)
# Dataset attributes
dset.attrs['description'] = 'Cumulative LOS displacement relative to reference date'
dset.attrs['units'] = 'meters' # Note: meters, not radians!
dset.attrs['acquisition_date'] = date_str
dset.attrs['reference_date'] = '20240101' # Should match track-level reference_date
print(f" Added dLOS_{date_str}")
print(f"\nā Created {filename}")
print(f" Explore with: h5ls -r {filename}")
print(f"\nNOTE: This file contains synthetic demo data.")
print("Replace the displacement generation with your actual time series data.")
7.1.3 Reading HDF5 Files
Example script demonstrating how to read InSAR HDF5 files and extract data.
#!/usr/bin/env python3
"""
Example: Reading InSAR HDF5 Files
Demonstrates how to read different product types
"""
import h5py
import numpy as np
# Adjust to your actual filename
filename = 'example_timeseries.h5'
with h5py.File(filename, 'r') as f:
# ============================================================
# 1. READ ROOT METADATA
# ============================================================
proc_type = f.attrs['processing_type']
print(f"Processing type: {proc_type}")
print(f"Software: {f.attrs['processing_software']}")
# ============================================================
# 2. READ TRACK METADATA
# ============================================================
# Adjust track name to match your file
track_name = 'ALOS2_073_A'
track = f[track_name]
print(f"\nTrack: {track_name}")
print(f" Platform: {track.attrs['platform']}")
print(f" Orbit: {track.attrs['relative_orbit']}")
print(f" Wavelength: {track.attrs['wavelength']:.4f} m")
# ============================================================
# 3. READ LOS VECTORS
# ============================================================
los_e = track['line_of_sight_e'][:]
los_n = track['line_of_sight_n'][:]
los_u = track['line_of_sight_u'][:]
print(f" LOS vectors shape: {los_e.shape}")
# ============================================================
# 4. READ DATA BASED ON PRODUCT TYPE
# ============================================================
if proc_type == 'INTERFEROGRAM':
print("\nReading interferogram...")
# List available interferogram date pairs
ifgs = [key for key in track.keys() if '_' in key and len(key) == 17]
print(f" Found {len(ifgs)} interferogram(s): {ifgs}")
# Read specific interferogram (adjust date pair to your data)
date_pair = '20240101_20240113'
ifg_group = track[date_pair]
unwrapped = ifg_group['unwrapped_interferogram'][:]
print(f" Unwrapped phase shape: {unwrapped.shape}")
print(f" Unwrapped range: [{unwrapped.min():.2f}, {unwrapped.max():.2f}] radians")
# Read coherence
correlation = ifg_group['correlation'][:]
print(f" Mean coherence: {correlation.mean():.3f}")
elif proc_type == 'DISP. TIME SERIES':
print("\nReading time series...")
# Get reference date (REQUIRED at track level)
ref_date = track.attrs['reference_date']
print(f" Reference date: {ref_date}")
# List all displacement dates
dates = sorted([key.replace('dLOS_', '') for key in track.keys()
if key.startswith('dLOS_')])
print(f" Found {len(dates)} date(s): {dates}")
# Read specific date (adjust to your data)
date_to_read = '20240113'
disp = track[f'dLOS_{date_to_read}'][:]
print(f" Displacement shape: {disp.shape}")
print(f" Displacement range: [{disp.min():.4f}, {disp.max():.4f}] meters")
elif proc_type == 'LOS_VELOCITY':
print("\nReading velocity...")
velocity = track['velocity'][:]
print(f" Velocity shape: {velocity.shape}")
print(f" Velocity range: [{velocity.min():.4f}, {velocity.max():.4f}] m/year")
# Read uncertainty if available
if 'velocity_std' in track:
velocity_std = track['velocity_std'][:]
print(f" Mean uncertainty: {velocity_std.mean():.4f} m/year")
print("\nā File read successfully")
š” Adapting Python Examples for Your Data:
- Replace synthetic data: Look for
# TODO:comments marking where to insert your actual arrays - Update dimensions: Change
demo_shape = (1000, 1200)to match your data size - Update metadata: Modify platform, orbit, dates, and other parameters to match your processing
- Add multiple tracks: Duplicate the track creation sections with different names and geometries
- Include all your dates: Expand the dates list for time series or add more date-pair groups for interferograms
- Load your data: Use your preferred method (GDAL, rasterio, numpy.load, etc.) to read your processed results
7.2 MATLAB Examples
7.2.1 Creating an INTERFEROGRAM File
This example script shows the structure for interferogram products. Adapt the data generation sections to match your actual processed interferograms.
%% Example: Creating an Interferogram HDF5 File (Version 2.0)
% This script demonstrates the HDF5 format structure
% Replace demo data generation with your actual interferogram data
clear; clc;
filename = 'example_interferogram.h5';
if exist(filename, 'file'), delete(filename); end
%% 1. Root-level metadata (file-wide)
h5writeatt(filename, '/', 'processing_type', 'INTERFEROGRAM');
h5writeatt(filename, '/', 'processing_software', 'ISCE2 v2.6.3 + SNAPHU v2.0.5');
h5writeatt(filename, '/', 'history', char(datetime('now', 'Format', 'yyyy-MM-dd''T''HH:mm:ss')));
h5writeatt(filename, '/', 'sign_convention', ...
'Positive LOS displacement corresponds to surface motion toward the sensor');
%% 2. Track-level metadata
track_path = '/ALOS2_073_A';
% REQUIRED metadata
h5writeatt(filename, track_path, 'platform', 'ALOS-2');
h5writeatt(filename, track_path, 'relative_orbit', int32(73));
h5writeatt(filename, track_path, 'flight_direction', 'A');
h5writeatt(filename, track_path, 'look_direction', 'R');
h5writeatt(filename, track_path, 'beam_mode', 'WD1');
h5writeatt(filename, track_path, 'beam_swath', 'W1');
h5writeatt(filename, track_path, 'wavelength', 0.236);
h5writeatt(filename, track_path, 'first_date', '2024-01-01');
h5writeatt(filename, track_path, 'last_date', '2024-02-08');
h5writeatt(filename, track_path, 'time_acquisition', '10:23');
h5writeatt(filename, track_path, 'scene_footprint', ...
'POLYGON((-118.5 34.0, -118.0 34.0, -118.0 34.5, -118.5 34.5, -118.5 34.0))');
% Optional but recommended
h5writeatt(filename, track_path, 'polarization', 'VV');
%% 3. LOS vectors (replace with your actual LOS geometry)
% TODO: Replace this with your actual LOS vectors
demo_shape = [1000, 1200]; % [rows, cols] - adjust to your data size
% Generate synthetic LOS vectors for demonstration
los_e = 0.35 + 0.10 * rand(demo_shape, 'single');
los_n = -0.05 + 0.10 * rand(demo_shape, 'single');
los_u = 0.75 + 0.10 * rand(demo_shape, 'single');
% Normalize to unit vectors
magnitude = sqrt(los_e.^2 + los_n.^2 + los_u.^2);
los_e = los_e ./ magnitude;
los_n = los_n ./ magnitude;
los_u = los_u ./ magnitude;
% Write LOS datasets with compression
h5create(filename, [track_path '/line_of_sight_e'], demo_shape, ...
'Datatype', 'single', 'ChunkSize', [100 100], 'Deflate', 6);
h5write(filename, [track_path '/line_of_sight_e'], los_e);
h5writeatt(filename, [track_path '/line_of_sight_e'], 'units', 'dimensionless');
h5create(filename, [track_path '/line_of_sight_n'], demo_shape, ...
'Datatype', 'single', 'ChunkSize', [100 100], 'Deflate', 6);
h5write(filename, [track_path '/line_of_sight_n'], los_n);
h5writeatt(filename, [track_path '/line_of_sight_n'], 'units', 'dimensionless');
h5create(filename, [track_path '/line_of_sight_u'], demo_shape, ...
'Datatype', 'single', 'ChunkSize', [100 100], 'Deflate', 6);
h5write(filename, [track_path '/line_of_sight_u'], los_u);
h5writeatt(filename, [track_path '/line_of_sight_u'], 'units', 'dimensionless');
%% 4. Interferogram data (replace with your actual phase data)
date_path = [track_path '/20240101_20240113'];
% Interferogram metadata
h5writeatt(filename, date_path, 'reference_date', '20240101');
h5writeatt(filename, date_path, 'secondary_date', '20240113');
h5writeatt(filename, date_path, 'temporal_baseline_days', int32(12));
h5writeatt(filename, date_path, 'baseline_perp', 45.2);
% TODO: Replace this synthetic data with your actual unwrapped interferogram
% Generate synthetic unwrapped phase for demonstration
[X, Y] = meshgrid(linspace(0, 4*pi, demo_shape(2)), linspace(0, 4*pi, demo_shape(1)));
unwrapped = single(sin(X/3) .* cos(Y/3) * 2 * pi);
h5create(filename, [date_path '/unwrapped_interferogram'], demo_shape, ...
'Datatype', 'single', 'ChunkSize', [100 100], 'Deflate', 6);
h5write(filename, [date_path '/unwrapped_interferogram'], unwrapped);
h5writeatt(filename, [date_path '/unwrapped_interferogram'], 'units', 'radians');
h5writeatt(filename, [date_path '/unwrapped_interferogram'], 'unwrap_method', 'SNAPHU');
% Wrapped phase
wrapped = single(angle(exp(1i * unwrapped)));
h5create(filename, [date_path '/wrapped_interferogram'], demo_shape, ...
'Datatype', 'single', 'ChunkSize', [100 100], 'Deflate', 6);
h5write(filename, [date_path '/wrapped_interferogram'], wrapped);
h5writeatt(filename, [date_path '/wrapped_interferogram'], 'units', 'radians');
% TODO: Replace with your actual coherence data
% Generate synthetic coherence for demonstration
coherence = single(0.5 + 0.4 * rand(demo_shape));
h5create(filename, [date_path '/correlation'], demo_shape, ...
'Datatype', 'single', 'ChunkSize', [100 100], 'Deflate', 6);
h5write(filename, [date_path '/correlation'], coherence);
h5writeatt(filename, [date_path '/correlation'], 'units', 'dimensionless');
fprintf('ā Created %s\n', filename);
fprintf(' Explore with: h5disp(''%s'')\n\n', filename);
fprintf('NOTE: This file contains synthetic demo data.\n');
fprintf('Replace the data generation sections with your actual interferogram data.\n');
7.2.2 Creating a TIME SERIES File
This example shows how to structure displacement time series data. Replace the synthetic displacement with your actual time series results.
%% Example: Creating a Time Series HDF5 File (Version 2.0)
% This script demonstrates the time series format structure
% Replace demo data with your actual time series displacements
clear; clc;
filename = 'example_timeseries.h5';
if exist(filename, 'file'), delete(filename); end
%% 1. Root-level metadata
h5writeatt(filename, '/', 'processing_type', 'DISP. TIME SERIES');
h5writeatt(filename, '/', 'processing_software', 'MintPy v1.5.1');
h5writeatt(filename, '/', 'history', char(datetime('now', 'Format', 'yyyy-MM-dd''T''HH:mm:ss')));
h5writeatt(filename, '/', 'sign_convention', ...
'Positive LOS displacement corresponds to surface motion toward the sensor');
%% 2. Track-level metadata
track_path = '/ALOS2_073_A';
% REQUIRED metadata
h5writeatt(filename, track_path, 'platform', 'ALOS-2');
h5writeatt(filename, track_path, 'relative_orbit', int32(73));
h5writeatt(filename, track_path, 'flight_direction', 'A');
h5writeatt(filename, track_path, 'look_direction', 'R');
h5writeatt(filename, track_path, 'beam_mode', 'WD1');
h5writeatt(filename, track_path, 'beam_swath', 'W1');
h5writeatt(filename, track_path, 'wavelength', 0.236);
h5writeatt(filename, track_path, 'first_date', '2024-01-01');
h5writeatt(filename, track_path, 'last_date', '2024-04-01');
h5writeatt(filename, track_path, 'time_acquisition', '10:23');
% REQUIRED for time series: track-specific reference date
h5writeatt(filename, track_path, 'reference_date', '20240101');
% Optional
h5writeatt(filename, track_path, 'polarization', 'VV');
%% 3. LOS vectors (replace with your actual LOS geometry)
% TODO: Replace with your actual LOS vectors
demo_shape = [1000, 1200]; % [rows, cols] - adjust to your data size
los_e = 0.35 + 0.10 * rand(demo_shape, 'single');
los_n = -0.05 + 0.10 * rand(demo_shape, 'single');
los_u = 0.75 + 0.10 * rand(demo_shape, 'single');
magnitude = sqrt(los_e.^2 + los_n.^2 + los_u.^2);
los_e = los_e ./ magnitude;
los_n = los_n ./ magnitude;
los_u = los_u ./ magnitude;
h5create(filename, [track_path '/line_of_sight_e'], demo_shape, ...
'Datatype', 'single', 'ChunkSize', [100 100], 'Deflate', 6);
h5write(filename, [track_path '/line_of_sight_e'], los_e);
h5writeatt(filename, [track_path '/line_of_sight_e'], 'units', 'dimensionless');
h5create(filename, [track_path '/line_of_sight_n'], demo_shape, ...
'Datatype', 'single', 'ChunkSize', [100 100], 'Deflate', 6);
h5write(filename, [track_path '/line_of_sight_n'], los_n);
h5writeatt(filename, [track_path '/line_of_sight_n'], 'units', 'dimensionless');
h5create(filename, [track_path '/line_of_sight_u'], demo_shape, ...
'Datatype', 'single', 'ChunkSize', [100 100], 'Deflate', 6);
h5write(filename, [track_path '/line_of_sight_u'], los_u);
h5writeatt(filename, [track_path '/line_of_sight_u'], 'units', 'dimensionless');
%% 4. Displacement time series (replace with your actual displacements)
dates = {'20240101', '20240113', '20240125', '20240208'};
fprintf('Creating time series with %d dates...\n', length(dates));
for i = 1:length(dates)
date_str = dates{i};
% TODO: Replace this synthetic data with your actual displacement data
if i == 1
% Reference date: all zeros
disp_data = zeros(demo_shape, 'single');
else
% Cumulative displacement in meters
% This is synthetic - replace with your actual time series data
disp_data = single(randn(demo_shape) * 0.01 * (i-1));
end
% Write dataset: dLOS_YYYYMMDD (note: directly under track, not in subgroups)
dataset_path = [track_path '/dLOS_' date_str];
h5create(filename, dataset_path, demo_shape, ...
'Datatype', 'single', 'ChunkSize', [100 100], 'Deflate', 6);
h5write(filename, dataset_path, disp_data);
% Dataset attributes
h5writeatt(filename, dataset_path, 'units', 'meters'); % Note: meters, not radians!
h5writeatt(filename, dataset_path, 'acquisition_date', date_str);
h5writeatt(filename, dataset_path, 'reference_date', '20240101');
fprintf(' Added dLOS_%s\n', date_str);
end
fprintf('\nā Created %s\n', filename);
fprintf(' Explore with: h5disp(''%s'')\n\n', filename);
fprintf('NOTE: This file contains synthetic demo data.\n');
fprintf('Replace the displacement generation with your actual time series data.\n');
7.2.3 Reading HDF5 Files
Helper script to read and display InSAR HDF5 file contents.
%% Example: Reading InSAR HDF5 Files
% Demonstrates how to read different product types
clear; clc;
% Adjust to your actual filename
filename = 'example_timeseries.h5';
%% 1. Read root metadata
proc_type = h5readatt(filename, '/', 'processing_type');
fprintf('Processing type: %s\n', proc_type);
%% 2. Read track metadata
track = 'ALOS2_073_A'; % Adjust to your track name
platform = h5readatt(filename, ['/' track], 'platform');
wavelength = h5readatt(filename, ['/' track], 'wavelength');
fprintf('Platform: %s, Wavelength: %.4f m\n', platform, wavelength);
%% 3. Read LOS vectors
los_e = h5read(filename, ['/' track '/line_of_sight_e']);
los_n = h5read(filename, ['/' track '/line_of_sight_n']);
los_u = h5read(filename, ['/' track '/line_of_sight_u']);
fprintf('LOS vectors size: %s\n', mat2str(size(los_e)));
%% 4. Read data based on product type
if strcmp(proc_type, 'INTERFEROGRAM')
fprintf('\nReading interferogram...\n');
% Read specific interferogram (adjust dates to your data)
date_pair = '20240101_20240113';
unwrapped = h5read(filename, ['/' track '/' date_pair '/unwrapped_interferogram']);
fprintf(' Unwrapped phase range: [%.2f, %.2f] radians\n', ...
min(unwrapped(:)), max(unwrapped(:)));
% Visualize
figure;
imagesc(unwrapped);
colorbar;
title('Unwrapped Phase (radians)');
axis equal tight;
elseif strcmp(proc_type, 'DISP. TIME SERIES')
fprintf('\nReading time series...\n');
% Get reference date (REQUIRED at track level)
ref_date = h5readatt(filename, ['/' track], 'reference_date');
fprintf(' Reference date: %s\n', ref_date);
% Read specific date (adjust to your data)
date_to_read = '20240113';
disp_data = h5read(filename, ['/' track '/dLOS_' date_to_read]);
fprintf(' Displacement range: [%.4f, %.4f] m\n', ...
min(disp_data(:)), max(disp_data(:)));
% Visualize
figure;
imagesc(disp_data);
colorbar;
title(sprintf('LOS Displacement: %s (meters)', date_to_read));
axis equal tight;
elseif strcmp(proc_type, 'LOS_VELOCITY')
fprintf('\nReading velocity...\n');
velocity = h5read(filename, ['/' track '/velocity']);
fprintf(' Velocity range: [%.4f, %.4f] m/year\n', ...
min(velocity(:)), max(velocity(:)));
% Visualize
figure;
imagesc(velocity);
colorbar;
title('LOS Velocity (m/year)');
axis equal tight;
end
fprintf('\nā File read successfully\n');
š” Adapting MATLAB Examples for Your Data:
- Replace demo data generation: Look for
% TODO:comments marking sections where you should load your actual data - Update metadata: Change platform names, orbits, dates, and other metadata to match your processing
- Adjust array sizes: Change
demo_shape = [1000, 1200]to your actual data dimensions - Add multiple tracks: Duplicate the track sections with different track names and geometries
- Include all dates: Add more date-pair groups for interferograms or expand the dates cell array for time series
- Load your data: Use
imread,geotiffread,load, or other methods to read your processed results

