Skip to content

Fix and simplify how user supplied reference pixel is validated #367

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

Merged
merged 1 commit into from
Nov 1, 2021

Conversation

adeane-ga
Copy link
Contributor

@adeane-ga adeane-ga commented Oct 21, 2021

This is a small PR that simplifies the way that the user supplied reference pixel is validated (confirmed to be within spatial extent). Without this fix, PyRate does not work if trying to crop in combination to supplying reference pixel coordinates - a very common user case.

It is associated with this issue: #360

Recommended Review Strategy
On your own testing dataset, run PyRate with the different combinations of cropping and user supplied reference pixel coordinates to confirm it is working for you and has also not broken anything.

The Problem
PyRate gives configuration options for the user to determine where the reference pixel will be refx and refy in longitude and latitude. There is also the option to crop the dataset with user defined coordinates so that PyRate only processes a smaller extent with ifgcropopt: 3. It is common for a user to use both of these options. The reference pixel selection is done during the correct step, whilst the cropping is conducted prior, in the prepifg step.

  • PyRate has a function inside refpix.py called __validate_supplied_lat_lon(). It is designed to confirm that the user supplied coordinates for the reference pixel are within the interferogram extent.
  • To obtain the spatial extent, the above function calls another function get_analysis_extent() which sits inside of prepifg_helper.py.
  • This sets off a sequence of other unrelated checks because this function was designed to operate during the prepifg step. One of these functions is to validate that user supplied cropping coordinates are within the original interferogram extent. But by this stage of the processing (correct step), the interferogram has already been cropped.
  • So the comparison is comparing user supplied cropping extents which are to 3 decimal places to the newly cropped interferogram datasets which are to 7 decimal places.

It results in this error:

Traceback (most recent call last):
  File "/home/547/ad6200/PyRateVenv/bin/pyrate", line 11, in <module>
    load_entry_point('Py-Rate==0.6.0', 'console_scripts', 'pyrate')()
  File "/home/547/ad6200/PyRateVenv/lib/python3.7/site-packages/pyrate/main.py", line 116, in main
    correct.main(config)
  File "/home/547/ad6200/PyRateVenv/lib/python3.7/site-packages/pyrate/correct.py", line 142, in main
    return correct_ifgs(config)
  File "/home/547/ad6200/PyRateVenv/lib/python3.7/site-packages/pyrate/correct.py", line 226, in correct_ifgs
    params[C.REFX_FOUND], params[C.REFY_FOUND] = ref_pixel_calc_wrapper(params)
  File "/home/547/ad6200/PyRateVenv/lib/python3.7/site-packages/pyrate/core/refpixel.py", line 423, in ref_pixel_calc_wrapper
    __validate_supplied_lat_lon(params)
  File "/home/547/ad6200/PyRateVenv/lib/python3.7/site-packages/pyrate/core/refpixel.py", line 401, in __validate_supplied_lat_lon
    C.IFG_XLAST], params[C.IFG_YLAST])
  File "/home/547/ad6200/PyRateVenv/lib/python3.7/site-packages/pyrate/core/prepifg_helper.py", line 81, in get_analysis_extent
    return _get_extents(rasters, crop_opt, user_exts)
  File "/home/547/ad6200/PyRateVenv/lib/python3.7/site-packages/pyrate/core/prepifg_helper.py", line 146, in _get_extents
    extents = _custom_bounds(ifgs, *user_exts)
  File "/home/547/ad6200/PyRateVenv/lib/python3.7/site-packages/pyrate/core/prepifg_helper.py", line 332, in _custom_bounds
    raise PreprocessError(msg)
pyrate.core.prepifg_helper.PreprocessError: Cropped image bounds are outside the original image bounds

Solution
As the above user supplied cropping coordinates check is not relevant during this step, I have removed the call to the get_analysis_extent() from the prepifg_helper.py and implemented a validation of the user supplied reference pixel by getting dataset extents independently from within the __validate_supplied_lat_lon() function itself.

In Summary

Old code:

def __validate_supplied_lat_lon(params: dict) -> None:
"""
Function to validate that the user supplied lat/lon values sit within image bounds
"""
lon, lat = params[C.REFX], params[C.REFY]
if lon == -1 or lat == -1:
return
xmin, ymin, xmax, ymax = prepifg_helper.get_analysis_extent(
crop_opt=params[C.IFG_CROP_OPT],
rasters=[prepifg_helper.dem_or_ifg(p.sampled_path) for p in params[C.INTERFEROGRAM_FILES]],
xlooks=params[C.IFG_LKSX], ylooks=params[C.IFG_LKSY],
user_exts=(params[C.IFG_XFIRST], params[C.IFG_YFIRST], params[
C.IFG_XLAST], params[C.IFG_YLAST])
)
msg = "Supplied {} value is outside the bounds of the interferogram data"
lat_lon_txt = ''
if (lon < xmin) or (lon > xmax):
lat_lon_txt += 'longitude'
if (lat < ymin) or (lat > ymax):
lat_lon_txt += ' and latitude' if lat_lon_txt else 'latitude'
if lat_lon_txt:
raise RefPixelError(msg.format(lat_lon_txt))

New code:

def __validate_supplied_lat_lon(params: dict) -> None:
"""
Function to validate that the user supplied lat/lon values sit within image bounds
"""
lon, lat = params[C.REFX], params[C.REFY]
if lon == -1 or lat == -1:
return
# Get extent of first IFG
src = gdal.Open(params[C.INTERFEROGRAM_FILES][0].sampled_path, gdal.GA_ReadOnly)
x_upleft, x_post, _, y_upleft, _, y_post = src.GetGeoTransform()
# Assign coordinates
xmin = x_upleft
ymax = y_upleft
xmax = x_upleft + (src.RasterXSize * x_post)
ymin = y_upleft + (src.RasterYSize * y_post)
# Close IFG file
src = None
msg = "Supplied {} value is outside the bounds of the interferogram data"
lat_lon_txt = ''
if (lon < xmin) or (lon > xmax):
lat_lon_txt += 'longitude'
if (lat < ymin) or (lat > ymax):
lat_lon_txt += ' and latitude' if lat_lon_txt else 'latitude'
if lat_lon_txt:
raise RefPixelError(msg.format(lat_lon_txt))

@s-m-t-c
Copy link
Contributor

s-m-t-c commented Nov 1, 2021

I have tested this feature with varying combinations of cropping and reference pixel options. Happy to merge this.

Initially I had an issue in the stacking step which implied that the cropping wasn't working correctly but a clean reinstall managed to fix this. Other users weren't able to recreate this.

IndexError: boolean index did not match indexed array along dimension 1; dimension is 60 but corresponding boolean dimension is 50

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants