[Feature] Add Hawkeye option#771
Conversation
|
TODOS
|
The method previously handled argument validation, inset construction, and indicator drawing in one long block. It now delegates to a _HawkeyeSpec dataclass carrying the normalized inputs and three narrow helpers: _resolve_hawkeye_spec validates and normalizes the arguments, _build_hawkeye_inset creates and geometrically configures the inset, and _add_hawkeye_indicator draws the extent indicator and connectors. The circular-boundary and indicator-patch logic move into stateless module helpers. Behavior is unchanged; the hawkeye tests gain coverage of the indicator-disabled path, the overview leader connector, and the invalid-relation guard.
matplotlib 3.10 changed Axes.indicate_inset_zoom to return an InsetIndicator artist exposing .rectangle and .connectors, whereas earlier versions such as 3.9 return a plain (rectangle, connectors) tuple. The corners-plus-detail hawkeye path stored that raw return on the inset, so accessing .connectors raised AttributeError on matplotlib 3.9. A new _add_hawkeye_zoom_indicator helper wraps the legacy tuple in a simple namespace so callers can rely on the same .rectangle and .connectors accessors on every supported version. A test forces the legacy tuple return to exercise the normalization on newer matplotlib as well.
When corner connectors join a detail hawkeye to a diagonally placed inset, matplotlib's indicate_inset_zoom chose a parallel pair of connectors running along one side instead of the two outer-tangent connectors that wrap the inset, so the callout did not read as a zoom frustum. matplotlib fixes connector visibility only once, from a bounding-box rule, so a draw-time hook now recomputes the enveloping pair from the sign of the inset-to-indicator centre offset once the inset locator has resolved the final positions. This covers both the modern InsetIndicator and the legacy tuple return. A test pins the visible pair for both diagonal placements.
Every other hawkeye keyword is singular and the argument selects a single mode rather than a sequence, so plural was both inconsistent with its siblings and misleading about what it accepts. The public parameter, its docstring, the spec field, and the parsing helper are now singular, while the result attribute inset._hawkeye_connectors stays plural because it holds the collection of drawn connector lines. Since hawkeye is unreleased this needs no deprecation.
origin/main only contains #772, which reverts the hawkeye/circular-inset commits that were mis-merged there; that work belongs on this branch. Merge with the 'ours' strategy so main is recorded as integrated while the feature branch keeps its hawkeye implementation intact. When this branch later merges back into main via its PR, the revert becomes the merge base and the hawkeye code is re-added cleanly.
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
|
I think we can ignore the visual regression as I didn't touch the code for the inset. I am opening this up. |
| ) | ||
|
|
||
|
|
||
| def _parse_hawkeye_anchor(anchor): |
There was a problem hiding this comment.
Can you add a paramter for anchor transform, to support point of coordinates to be anchor. Like ax.hawkeye(anchor=(103, 38), anchor_transform='map/or data/or crs'
There was a problem hiding this comment.
This could be possible as this:
ax.hawkeye(
(103, 38),
size=0.2,
transform="map", # longitude/latitude (PlateCarree)
anchor="upper right", # inset box corner
)
|
inax = ax.hawkeye( |
|
The circular inset will now prompt redraw on the limits similar to how the inset do it. |
| locator = self._make_inset_locator(bounds, transform) | ||
| # Convert coordinates to figure-relative coordinates while retaining the | ||
| # original bounds for aspect-aware geographic inset locators. | ||
| bounds_input, transform = self._parse_anchor(bounds, transform, default="axes") |
There was a problem hiding this comment.
I didn't understand the logic here. Can you explain it? Or simple example?
|
I'd like to discuss a few coordinate‑system design aspects of the The
There is also a My questions and suggestions are as follows: 1. About the
2. About the However, the current implementation forces
I hope this clarifies my design intent. I look forward to your thoughts. |
|
1.2 'data' -> ax.transData, that is, I assume here that your input will already be in your projected units. A CRS will go through For 2 I think this is a good addition to also allow pinning to the data coordinates, it currently defaults to axes. Does this clear things up? |
|
So my read is that
|
|
Everything is fine now, apart from the "map" transform. I apologize for my earlier comment—it was poorly considered and may have misled you. Since "map" is not supported as a transform name in the GeoAxes transform system, I believe we should drop it from hawkeye. Let's keep the transform parsing consistent for both GeoAxes and the hawkeye method. All others works fine as I tested. |



Closes #770
This PR extends the options for annotation on
GeoAxes. It add specific "hawkeye" insets for GeoAxes to highlight specific areas of the map. It both adds square as well as circular annotations. Examples:Succinctly this is now wired in as:
aspect="auto" instead fits an exact extent with distortion.