-
Notifications
You must be signed in to change notification settings - Fork 64
feat: add mil and inch units to plot_length_units #2690
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
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
5 files reviewed, 1 comment
Diff CoverageDiff: origin/develop...HEAD, staged and unstaged changes
Summary
tidy3d/components/viz/axes_utils.pyLines 25-88 25 super().__init__()
26 self.scale_factor = scale_factor
27
28 def __call__(self):
! 29 vmin, vmax = self.axis.get_view_interval()
! 30 return self.tick_values(vmin, vmax)
31
32 def view_limits(self, vmin, vmax):
33 """Override to prevent matplotlib from adjusting our limits."""
! 34 return vmin, vmax
35
36 def tick_values(self, vmin, vmax):
37 # convert the view range to the target unit
! 38 vmin_unit = vmin * self.scale_factor
! 39 vmax_unit = vmax * self.scale_factor
40
41 # tolerance for floating point comparisons in target unit
! 42 unit_range = vmax_unit - vmin_unit
! 43 unit_tol = unit_range * 1e-8
44
! 45 locator = ticker.MaxNLocator(nbins=11, prune=None, min_n_ticks=2)
46
! 47 ticks_unit = locator.tick_values(vmin_unit, vmax_unit)
48
49 # ensure we have ticks that cover the full range
! 50 if len(ticks_unit) > 0:
! 51 if ticks_unit[0] > vmin_unit + unit_tol or ticks_unit[-1] < vmax_unit - unit_tol:
52 # try with fewer bins to get better coverage
! 53 for n in [10, 9, 8, 7, 6, 5]:
! 54 locator = ticker.MaxNLocator(nbins=n, prune=None, min_n_ticks=2)
! 55 ticks_unit = locator.tick_values(vmin_unit, vmax_unit)
! 56 if (
57 len(ticks_unit) >= 3
58 and ticks_unit[0] <= vmin_unit + unit_tol
59 and ticks_unit[-1] >= vmax_unit - unit_tol
60 ):
! 61 break
62
63 # if still no good coverage, manually ensure edge coverage
! 64 if len(ticks_unit) > 0:
! 65 if (
66 ticks_unit[0] > vmin_unit + unit_tol
67 or ticks_unit[-1] < vmax_unit - unit_tol
68 ):
69 # find a reasonable step size from existing ticks
! 70 if len(ticks_unit) > 1:
! 71 step = ticks_unit[1] - ticks_unit[0]
72 else:
! 73 step = unit_range / 5
74
75 # extend the range to ensure coverage
! 76 extended_min = vmin_unit - step
! 77 extended_max = vmax_unit + step
78
79 # try one more time with extended range
! 80 locator = ticker.MaxNLocator(nbins=8, prune=None, min_n_ticks=2)
! 81 ticks_unit = locator.tick_values(extended_min, extended_max)
82
83 # filter to reasonable bounds around the original range
! 84 ticks_unit = [
85 t
86 for t in ticks_unit
87 if t >= vmin_unit - step / 2 and t <= vmax_unit + step / 2
88 ] Lines 87-99 87 if t >= vmin_unit - step / 2 and t <= vmax_unit + step / 2
88 ]
89
90 # convert the nice ticks back to the original data unit (micrometers)
! 91 ticks_um = ticks_unit / self.scale_factor
92
93 # filter to ensure ticks are within bounds (with small tolerance)
! 94 eps = (vmax - vmin) * 1e-8
! 95 return [tick for tick in ticks_um if vmin - eps <= tick <= vmax + eps]
96
97 return UnitAwareLocator
98 |
308c01d
to
3c1e3f2
Compare
ed946ef
to
a5a77fe
Compare
a5a77fe
to
b868d6d
Compare
daquinteroflex
approved these changes
Aug 7, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
#2655 was merged accidentally so this is back for after the 2.9 release. refer to comments in that PR, the changes are identical
Greptile Summary
This PR adds support for imperial length units ('mil' and 'in') to the
plot_length_units
functionality in Tidy3D. The change addresses the need for users working with PCB designs and semiconductor layouts who prefer to visualize geometries in imperial units.The implementation involves four key components:
LengthUnit
Literal type intypes.py
to include 'mil' and 'in' alongside existing metric unitsUnitScaling
dictionary inconstants.py
, complementing the existing 'in' unitUnitAwareLocator
class inaxes_utils.py
that intelligently positions matplotlib ticks for imperial units, addressing the issue where default tick placement produces awkward decimal values due to the conversion from micrometersThe feature integrates seamlessly with Tidy3D's existing plotting infrastructure. The custom locator is only applied to imperial units ('mil' and 'in'), preserving existing behavior for metric units. This ensures users see intuitive tick values like 0.1, 0.2, 0.5 mil instead of awkward decimals when plotting in imperial units.
According to the PR description, this is a re-implementation of changes from PR #2655 that were accidentally merged and then reverted for the 2.9 release.
Confidence score: 4.5/5
axes_utils.py
file needs careful review due to its complex tick placement logic and potential edge cases in the range extension and fallback mechanisms