-
Notifications
You must be signed in to change notification settings - Fork 297
prep_gmtsar: grab A/RLOOKS from GMTSAR config file if available
#1389
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
+ utils.readfile.read_gmtsar_prm(): support reading GMTSAR config file, which may have empty key values or may not have some keys as in the PRM file + prep_gmtsar.extract_gmtsar_metadata(): support grabing A/RLOOKS from the config.tops.txt file if available + docs/dir_structure.md: add config.tops.txt file to the example directory + docs/demo_dataset.md: update the zenodo link for the new example dataset (with the config.tops.txt file added)
Reviewer's GuideThis PR enhances GMTSAR parameter handling by improving the parser to skip empty entries and conditionally map attributes, augments metadata extraction to pull processing looks from an external config file (with template fallback) while updating pixel sizing, adds targeted debug logging throughout prep_gmtsar, tweaks the heading-to-azimuth conversion for right-looking geometry, and brings documentation up to date with the new config file and demo dataset link. Sequence diagram for extracting A/RLOOKS from config or template in GMTSAR metadata extractionsequenceDiagram
participant User
participant prep_gmtsar.extract_gmtsar_metadata
participant readfile.read_gmtsar_prm
participant readfile.read_template
participant config_file
participant template_file
User->>prep_gmtsar.extract_gmtsar_metadata: Call with meta_file, unw_file, template_file
prep_gmtsar.extract_gmtsar_metadata->>readfile.read_gmtsar_prm: Read meta_file
readfile.read_gmtsar_prm-->>prep_gmtsar.extract_gmtsar_metadata: Return meta dict
prep_gmtsar.extract_gmtsar_metadata->>config_file: Check if config.tops.txt exists
alt config file exists
prep_gmtsar.extract_gmtsar_metadata->>readfile.read_gmtsar_prm: Read config_file
readfile.read_gmtsar_prm-->>prep_gmtsar.extract_gmtsar_metadata: Return config dict
prep_gmtsar.extract_gmtsar_metadata->>prep_gmtsar.extract_gmtsar_metadata: Calculate ALOOKS/RLOOKS from config
else config file missing
prep_gmtsar.extract_gmtsar_metadata->>readfile.read_template: Read template_file
readfile.read_template-->>prep_gmtsar.extract_gmtsar_metadata: Return template dict
prep_gmtsar.extract_gmtsar_metadata->>prep_gmtsar.extract_gmtsar_metadata: Get ALOOKS/RLOOKS from template
end
prep_gmtsar.extract_gmtsar_metadata->>prep_gmtsar.extract_gmtsar_metadata: Update pixel sizes
prep_gmtsar.extract_gmtsar_metadata-->>User: Return updated metadata
Class diagram for updated GMTSAR parameter reading and metadata extractionclassDiagram
class readfile {
+read_gmtsar_prm(fname, delimiter='=')
+read_template(template_file)
}
class prep_gmtsar {
+extract_gmtsar_metadata(meta_file, unw_file, template_file, ...)
}
readfile <.. prep_gmtsar : uses
class read_gmtsar_prm {
+skips empty key values
+conditionally maps SC_clock_start/stop and SC_identity
}
readfile ..> read_gmtsar_prm : calls
class extract_gmtsar_metadata {
+reads ALOOKS/RLOOKS from config or template
+updates AZIMUTH/RANGE_PIXEL_SIZE
}
prep_gmtsar ..> extract_gmtsar_metadata : main logic
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @yunjunz - I've reviewed your changes and they look great!
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location> `src/mintpy/prep_gmtsar.py:93` </location>
<code_context>
return prm_dict
# read corners lat/lon info
+ print(f'grab LAT/LON_REF1/2/3/4 from file: {geo_file}')
ds = gdal.Open(geo_file, gdal.GA_ReadOnly)
transform = ds.GetGeoTransform()
</code_context>
<issue_to_address>
Consider replacing print statements with a logging framework.
A logging framework provides better control over message levels and output, reducing clutter in standard output.
Suggested implementation:
```python
return prm_dict
import logging
logging.basicConfig(level=logging.INFO)
# read corners lat/lon info
logging.info(f'grab LAT/LON_REF1/2/3/4 from file: {geo_file}')
ds = gdal.Open(geo_file, gdal.GA_ReadOnly)
transform = ds.GetGeoTransform()
```
```python
# read width from rdr_file
logging.info(f'grab SLANT_RANGE_DISTANCE, INCIDENCE_ANGLE from file: {geo_file}')
ds = gdal.Open(geo_file, gdal.GA_ReadOnly)
width = ds.RasterXSize
```
</issue_to_address>
### Comment 2
<location> `src/mintpy/prep_gmtsar.py:142` </location>
<code_context>
raise ValueError(f'No radar-coord files found in {ifg_dir} with suffix: {fbases}')
# read width from rdr_file
+ print(f'grab SLANT_RANGE_DISTANCE, INCIDENCE_ANGLE from file: {geo_file}')
ds = gdal.Open(geo_file, gdal.GA_ReadOnly)
width = ds.RasterXSize
</code_context>
<issue_to_address>
Prefer logging over print for status messages.
Using a logging library enhances maintainability and lets users control output verbosity.
Suggested implementation:
```python
import logging
logging.info(f'grab LAT/LON_REF1/2/3/4 from file: {geo_file}')
```
```python
logging.info(f'grab SLANT_RANGE_DISTANCE, INCIDENCE_ANGLE from file: {geo_file}')
```
```python
logging.info(f'extract metadata from metadata file: {meta_file}')
```
If `import logging` is already present at the top of the file, you can remove the new import statement from the first change above.
You may also want to ensure that logging is configured somewhere in your application, e.g., with `logging.basicConfig(level=logging.INFO)`, if not already done.
</issue_to_address>
### Comment 3
<location> `src/mintpy/prep_gmtsar.py:195` </location>
<code_context>
# 1. read *.PRM file
- #prm_file = get_prm_files(ifg_dir)[0]
+ # prm_file = get_prm_files(ifg_dir)[0]
+ print(f'extract metadata from metadata file: {meta_file}')
meta = readfile.read_gmtsar_prm(meta_file)
meta['PROCESSOR'] = 'gmtsar'
</code_context>
<issue_to_address>
Replace print with logging for better output control.
Logging offers more flexibility and can be easily managed or redirected in production environments.
Suggested implementation:
```python
# 1. read *.PRM file
# prm_file = get_prm_files(ifg_dir)[0]
import logging
logging.info(f'extract metadata from metadata file: {meta_file}')
meta = readfile.read_gmtsar_prm(meta_file)
meta['PROCESSOR'] = 'gmtsar'
```
If the `logging` module is already imported at the top of the file, you should remove the duplicate import from this block. Also, ensure that logging is configured somewhere in your application (e.g., with `logging.basicConfig(level=logging.INFO)`), otherwise you may not see any output.
</issue_to_address>
### Comment 4
<location> `src/mintpy/prep_gmtsar.py:210` </location>
<code_context>
+ # calc a/rlooks
+ # Note from Xiaohua Xu: GMTSAR is applying Gaussian filtering, instead of multilooing,
+ # thus, the equivalent value is ~0.3 times the mainlobe response of the boxcar filtering.
+ print(f'grab A/RLOOKS from config file: {config_file}')
+ meta['ALOOKS'] = np.rint(0.3 * filter_wvl / meta['AZIMUTH_PIXEL_SIZE']).astype(int)
+ meta['RLOOKS'] = np.rint(0.3 * filter_wvl / meta['RANGE_PIXEL_SIZE']).astype(int)
+
+ else:
</code_context>
<issue_to_address>
Consider using logging instead of print for configuration status.
Using logging allows users to adjust message verbosity and output location, which is beneficial in complex workflows.
Suggested implementation:
```python
logging.info(f'grab A/RLOOKS from config file: {config_file}')
```
```python
logging.warning(f'No config file found in {config_file}!')
```
```python
logging.info(f'grab {key} from template file: {template_file}')
```
```python
import logging
template = readfile.read_template(template_file)
```
</issue_to_address>
### Comment 5
<location> `src/mintpy/prep_gmtsar.py:215` </location>
<code_context>
+ meta['RLOOKS'] = np.rint(0.3 * filter_wvl / meta['RANGE_PIXEL_SIZE']).astype(int)
+
+ else:
+ print(f'WARNING: No config file found in {config_file}!')
+ # read from template file
+ for key in ['ALOOKS', 'RLOOKS']:
</code_context>
<issue_to_address>
Use logging.warning for warnings instead of print.
This allows warnings to be managed and filtered more effectively.
Suggested implementation:
```python
import logging
logging.info(f'grab A/RLOOKS from config file: {config_file}')
```
```python
import logging
logging.warning(f'No config file found in {config_file}!')
```
```python
logging.info(f'grab {key} from template file: {template_file}')
```
</issue_to_address>
### Comment 6
<location> `docs/demo_dataset.md:61` </location>
<code_context>
+ Area: San Francisco Bay, California, USA
-+ Data: Sentinel-1 A/B descending track 42 during December 2014 - June 2024 (333 acquisitoins; [Zenodo](https://zenodo.org/records/12773014))
++ Data: Sentinel-1 A/B descending track 42 during December 2014 - June 2024 (333 acquisitoins; [Zenodo](https://zenodo.org/records/15814132))
+ Size: ~2.3 GB
</code_context>
<issue_to_address>
Typo: 'acquisitoins' should be 'acquisitions'.
Please update the typo to 'acquisitions'.
</issue_to_address>
<suggested_fix>
<<<<<<< SEARCH
+ Data: Sentinel-1 A/B descending track 42 during December 2014 - June 2024 (333 acquisitoins; [Zenodo](https://zenodo.org/records/15814132))
=======
+ Data: Sentinel-1 A/B descending track 42 during December 2014 - June 2024 (333 acquisitions; [Zenodo](https://zenodo.org/records/15814132))
>>>>>>> REPLACE
</suggested_fix>Help me be more useful! Please click π or π on each comment and I'll use the feedback to improve your reviews.
| return prm_dict | ||
|
|
||
| # read corners lat/lon info | ||
| print(f'grab LAT/LON_REF1/2/3/4 from file: {geo_file}') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Consider replacing print statements with a logging framework.
A logging framework provides better control over message levels and output, reducing clutter in standard output.
Suggested implementation:
return prm_dict
import logging
logging.basicConfig(level=logging.INFO)
# read corners lat/lon info
logging.info(f'grab LAT/LON_REF1/2/3/4 from file: {geo_file}')
ds = gdal.Open(geo_file, gdal.GA_ReadOnly)
transform = ds.GetGeoTransform() # read width from rdr_file
logging.info(f'grab SLANT_RANGE_DISTANCE, INCIDENCE_ANGLE from file: {geo_file}')
ds = gdal.Open(geo_file, gdal.GA_ReadOnly)
width = ds.RasterXSize| raise ValueError(f'No radar-coord files found in {ifg_dir} with suffix: {fbases}') | ||
|
|
||
| # read width from rdr_file | ||
| print(f'grab SLANT_RANGE_DISTANCE, INCIDENCE_ANGLE from file: {geo_file}') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Prefer logging over print for status messages.
Using a logging library enhances maintainability and lets users control output verbosity.
Suggested implementation:
import logging
logging.info(f'grab LAT/LON_REF1/2/3/4 from file: {geo_file}') logging.info(f'grab SLANT_RANGE_DISTANCE, INCIDENCE_ANGLE from file: {geo_file}') logging.info(f'extract metadata from metadata file: {meta_file}')If import logging is already present at the top of the file, you can remove the new import statement from the first change above.
You may also want to ensure that logging is configured somewhere in your application, e.g., with logging.basicConfig(level=logging.INFO), if not already done.
| # 1. read *.PRM file | ||
| #prm_file = get_prm_files(ifg_dir)[0] | ||
| # prm_file = get_prm_files(ifg_dir)[0] | ||
| print(f'extract metadata from metadata file: {meta_file}') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Replace print with logging for better output control.
Logging offers more flexibility and can be easily managed or redirected in production environments.
Suggested implementation:
# 1. read *.PRM file
# prm_file = get_prm_files(ifg_dir)[0]
import logging
logging.info(f'extract metadata from metadata file: {meta_file}')
meta = readfile.read_gmtsar_prm(meta_file)
meta['PROCESSOR'] = 'gmtsar'If the logging module is already imported at the top of the file, you should remove the duplicate import from this block. Also, ensure that logging is configured somewhere in your application (e.g., with logging.basicConfig(level=logging.INFO)), otherwise you may not see any output.
| print(f'grab A/RLOOKS from config file: {config_file}') | ||
| meta['ALOOKS'] = np.rint(0.3 * filter_wvl / meta['AZIMUTH_PIXEL_SIZE']).astype(int) | ||
| meta['RLOOKS'] = np.rint(0.3 * filter_wvl / meta['RANGE_PIXEL_SIZE']).astype(int) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Consider using logging instead of print for configuration status.
Using logging allows users to adjust message verbosity and output location, which is beneficial in complex workflows.
Suggested implementation:
logging.info(f'grab A/RLOOKS from config file: {config_file}') logging.warning(f'No config file found in {config_file}!') logging.info(f'grab {key} from template file: {template_file}') import logging
template = readfile.read_template(template_file)
src/mintpy/prep_gmtsar.py
Outdated
| meta['RLOOKS'] = np.rint(0.3 * filter_wvl / meta['RANGE_PIXEL_SIZE']).astype(int) | ||
|
|
||
| else: | ||
| print(f'WARNING: No config file found in {config_file}!') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Use logging.warning for warnings instead of print.
This allows warnings to be managed and filtered more effectively.
Suggested implementation:
import logging
logging.info(f'grab A/RLOOKS from config file: {config_file}') import logging
logging.warning(f'No config file found in {config_file}!') logging.info(f'grab {key} from template file: {template_file}')Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Description of proposed changes
utils.readfile.read_gmtsar_prm(): support readingGMTSARconfig file, which may have empty key values or may not have some keys as in the PRM fileprep_gmtsar.extract_gmtsar_metadata(): support grabing A/RLOOKS from the config file if available, which is usually named as
config.{SAT}.txt, where SAT can be ERS, ENVI, ALOS, ALOS_SLC, ALOS2, ALOS2_SCAN, S1_STRIP, S1_TOPS, CSK_RAW, CSK_SLC, CSG, TSX, RS2, GF3, LT1, with help from @Xiaohua-Eric-Xu.docs/dir_structure.md: addconfig.tops.txtfile to the example directorydocs/demo_dataset.md: update the zenodo link for the new example dataset (with theconfig.tops.txtfile added)Reminders
Summary by Sourcery
Add robust GMTSAR config file support for metadata extraction, improve parameter parsing resilience, adjust radar look direction handling, and refresh relevant documentation examples.
New Features:
Enhancements:
Documentation: