-
Notifications
You must be signed in to change notification settings - Fork 297
add view --shp-file to plot line/polygon from ESRI shapefiles or GMT lonlat files
#1435
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
+ add Liu et al. (2025) to the reference + simplify the reference on the NNR-PMMs
…T lonlat files + utils.arg_utils.py: add `add_shape_argument()` to parse shape files from ESRI and GMT, including file path, color, linewidth, etc. The previous --faultline options are still supported for backward compatibility. + view: - add view.py --shp-file --shp-color --shp-linewidth options + utils.plot: add the following new functions: - add `plot_shapefile()` to read and plot ERSI shapefiles using gdal and plot using matplotlib - rename `plot_faultline()` to `plot_gmt_lonlat_file()` - add `plot_shape()` to call the above two functions.
Reviewer's GuideThis PR extends the Sequence diagram for plotting shapes from CLI to plotting routinessequenceDiagram
actor User
participant CLI["view.py"]
participant ArgParser["arg_utils.py"]
participant Plot["utils.plot.py"]
User->>CLI: Run view.py with --shp-file
CLI->>ArgParser: Parse --shp-file, --shp-color, --shp-lw, --shp-min-dist
ArgParser->>CLI: Return parsed arguments
CLI->>Plot: Call plot_shape(ax, shp_files, ...)
Plot->>Plot: For each shp_file, call plot_shapefile or plot_gmt_lonlat_file
Plot->>CLI: Return updated plot
Class diagram for new and updated plotting functions in utils.plotclassDiagram
class plot_shape {
+plot_shape(ax, shp_files, SNWE, color, linewidth, min_dist, print_msg)
}
class plot_shapefile {
+plot_shapefile(ax, shp_file, color, linewidth, print_msg)
}
class plot_gmt_lonlat_file {
+plot_gmt_lonlat_file(ax, shp_file, SNWE, min_dist, color, linewidth, print_msg)
}
plot_shape --> plot_shapefile : calls
plot_shape --> plot_gmt_lonlat_file : calls
Class diagram for argument parsing changes in arg_utils.pyclassDiagram
class add_shape_argument {
+add_shape_argument(parser)
--shp-file
--shp-color
--shp-lw
--shp-min-dist
}
class add_map_argument {
-removed: --faultline
-removed: --faultline-lw
-removed: --faultline-min-dist
}
add_shape_argument ..> add_map_argument : replaces faultline args
File-Level Changes
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 there - 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/utils/plot.py:1536-1537` </location>
<code_context>
+ if shp_file.endswith('.shp'):
+ plot_shapefile(ax, shp_file, **kwargs)
+
+ elif shp_file.endswith('.lonlat'):
+ plot_gmt_lonlat_file(ax, shp_file, SNWE, min_dist=0.1, print_msg=print_msg, **kwargs)
+
+ # keep the same axis limit
</code_context>
<issue_to_address>
**issue (bug_risk):** Hardcoded min_dist value may override user input.
Currently, plot_gmt_lonlat_file always uses min_dist=0.1, which ignores any min_dist value provided to plot_shape. Please pass the min_dist argument through to preserve user input.
</issue_to_address>
### Comment 2
<location> `src/mintpy/utils/plot.py:1622` </location>
<code_context>
+ ax.plot(geom.GetX(), geom.GetY(), "o", **kwargs)
+
+ else:
+ warning.warn(f'Un-recognized geometry type: {geom_type}! Ignore and continue.')
+
+ return ax
</code_context>
<issue_to_address>
**issue (typo):** Potential typo: 'warning.warn' should be 'warnings.warn'.
Using 'warning.warn' instead of 'warnings.warn' will cause a NameError unless 'warning' is defined.
</issue_to_address>
### Comment 3
<location> `src/mintpy/utils/arg_utils.py:477-481` </location>
<code_context>
+ """Argument group parser to plot shapes (line, polygon) in ERSI shapefile or GMT lonlat format."""
+ shp = parser.add_argument_group('Shapes', 'Plot various shapes (line, polygon) in ERSI or GMT format.')
+ shp.add_argument('--shp-file','--faultline', dest='shp_file', type=str, nargs='*',
+ help='Shape files in ERSI shapefile or GMT lonlat format.')
+ shp.add_argument('--shp-color', dest='shp_color', type=str, default='k',
+ help='Shape color (default: %(default)s).')
</code_context>
<issue_to_address>
**nitpick (typo):** Typo in help string: 'ERSI' should be 'ESRI'.
The help string should use 'ESRI shapefile' instead of 'ERSI shapefile' for accuracy.
```suggestion
def add_shape_argument(parser):
"""Argument group parser to plot shapes (line, polygon) in ESRI shapefile or GMT lonlat format."""
shp = parser.add_argument_group('Shapes', 'Plot various shapes (line, polygon) in ESRI or GMT format.')
shp.add_argument('--shp-file','--faultline', dest='shp_file', type=str, nargs='*',
help='Shape files in ESRI shapefile or GMT lonlat format.')
```
</issue_to_address>
### Comment 4
<location> `src/mintpy/utils/arg_utils.py:484-486` </location>
<code_context>
+ help='Shape color (default: %(default)s).')
+ shp.add_argument('--shp-lw','--shp-linewidth','--faultline-lw', dest='shp_linewidth',
+ default=0.5, type=float, metavar='NUM',
+ help='Shpae linewidth (default: %(default)s).')
+ shp.add_argument('--shp-min-dist','--faultline-min-dist', dest='shp_min_dist', type=float,
+ default=0.1, metavar='NUM',
</code_context>
<issue_to_address>
**nitpick (typo):** Typo in help string: 'Shpae' should be 'Shape'.
```suggestion
shp.add_argument('--shp-lw','--shp-linewidth','--faultline-lw', dest='shp_linewidth',
default=0.5, type=float, metavar='NUM',
help='Shape linewidth (default: %(default)s).')
```
</issue_to_address>
### Comment 5
<location> `src/mintpy/utils/plot.py:1547` </location>
<code_context>
+ return ax
+
+
+def plot_shapefile(ax, shp_file, color='k', linewidth=0.5, print_msg=True):
+ """Plot shapes (line or polygon) in ESRI shapefile format.
+
</code_context>
<issue_to_address>
**issue (complexity):** Consider refactoring plotting logic by introducing helper functions to unify and simplify geometry handling and plotting.
Here’s one way to collapse most of that nested/duplicated plotting logic by pulling out two small helpers:
```python
# new helper, anywhere near top‐level
def plot_sequences(ax, sequences, **kwargs):
"""Plot each (x,y) tuple in sequences on ax."""
for x, y in sequences:
ax.plot(x, y, **kwargs)
return ax
# new helper for OGR geometries
def iter_geom_coords(geom):
"""Yield (x, y) lists for any Polygon/MultiPolygon/LineString/…"""
t = geom.GetGeometryType()
# single Polygon
if t in (ogr.wkbPolygon, ogr.wkbPolygon25D):
for ring in geom:
pts = ring.GetPointCount()
yield ([ring.GetX(i) for i in range(pts)],
[ring.GetY(i) for i in range(pts)])
# multi‐polygon
elif t in (ogr.wkbMultiPolygon, ogr.wkbMultiPolygon25D):
for part in geom:
yield from iter_geom_coords(part)
# single LineString
elif t in (ogr.wkbLineString, ogr.wkbLineString25D):
pts = geom.GetPointCount()
yield ([geom.GetX(i) for i in range(pts)],
[geom.GetY(i) for i in range(pts)])
# multi‐line
elif t in (ogr.wkbMultiLineString, ogr.wkbMultiLineString25D):
for part in geom:
yield from iter_geom_coords(part)
# point
elif t == ogr.wkbPoint:
yield [geom.GetX()], [geom.GetY()]
# refactored plot_shapefile
def plot_shapefile(ax, shp_file, color='k', linewidth=0.5, print_msg=True):
from osgeo import ogr, osr
# … open ds, layer, build transform exactly as before …
kwargs = dict(color=color, linewidth=linewidth)
for feature in layer:
geom = feature.GetGeometryRef()
if not source_srs.IsGeographic():
if print_msg:
print("▶ converting to lon/lat…")
geom.Transform(transform)
# single loop over all coord sequences
ax = plot_sequences(ax, iter_geom_coords(geom), **kwargs)
return ax
# simplified GMT lonlat plotting
def plot_gmt_lonlat_file(ax, shp_file, SNWE, min_dist=0.1, **kwargs):
faults = readfile.read_gmt_lonlat_file(shp_file, SNWE=SNWE,
min_dist=min_dist,
print_msg=kwargs.pop('print_msg', True))
if not faults:
warnings.warn("…skip plotting")
return ax, faults
seqs = [(f[:,0], f[:,1]) for f in faults]
return plot_sequences(ax, seqs, **kwargs), faults
```
This:
- removes the nested `draw_polygon`,
- collapses all `if geom_type …` blocks into one generator,
- unifies plotting of shapefiles + GMT files via `plot_sequences`,
- eliminates repeated `ax.plot(…, color, linewidth)` calls.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Description of proposed changes
This PR adds
view.py --shp-file/color/linewidthoptions to plot line/polygon from ESRI shapefiles or GMT lonlat file format.utils.arg_utils.py: addadd_shape_argument()to parse shape files from ESRI and GMT, including file path, color, linewidth, etc. The previous--faultlinerelated options are still supported for backward compatibility.utils.plot: add the following new functions:plot_shapefile()to read and plot ERSI shapefiles using gdal and plot using matplotlibplot_faultline()toplot_gmt_lonlat_file()plot_shape()to call the above two functions.plate_motion.py:Reminders
Summary by Sourcery
Add support for plotting line and polygon shapes from ESRI shapefiles and GMT lonlat files via a new
--shp-fileinterface in view, backed by new plot_shapefile and plot_shape functions, and unify related argument parsing; also update plate_motion references.New Features:
--shp-file,--shp-color,--shp-lw, and--shp-min-distarguments to the view CLI for plotting ESRI shapefiles and GMT lonlat files.Enhancements:
Documentation:
--shp-fileusage.