Skip to content

Commit bb7916b

Browse files
authored
fix: render log ticks in mathtext (#1405)
### **User description** ## Summary - ensure log and symlog tick formatting never falls back to literal 0 for small positive powers of ten - wrap power-of-ten tick labels in mathtext delimiters so matplotlib renders superscripts - update log/symlog regression tests to expect the mathtext output ## Testing - make test - PATH="/tmp/fortplot_shim:$PATH" make verify-artifacts ___ ### **PR Type** Bug fix ___ ### **Description** - Wrap log/symlog tick labels in mathtext delimiters (`$...$`) - Fix zero value detection using epsilon comparison - Update test expectations for mathtext formatting - Improve log scale detection logic ___ ### Diagram Walkthrough ```mermaid flowchart LR A["Log/Symlog Ticks"] --> B["format_power_of_ten_label()"] B --> C["Add $...$ delimiters"] C --> D["Mathtext Rendered Labels"] E["Zero Detection"] --> F["Use epsilon() comparison"] F --> G["More Accurate Zero Handling"] ``` <details> <summary><h3> File Walkthrough</h3></summary> <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Bug fix</strong></td><td><table> <tr> <td> <details> <summary><strong>fortplot_axes.f90</strong><dd><code>Improve log scale detection and zero handling</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> src/ui/fortplot_axes.f90 <ul><li>Add <code>is_log_scale</code> variable for cleaner scale type checking<br> <li> Replace hardcoded epsilon with <code>epsilon(1.0_wp)</code> for zero detection<br> <li> Add separate zero handling for non-log scales with <code>TICK_EPS</code></ul> </details> </td> <td><a href="https://github.com/lazy-fortran/fortplot/pull/1405/files#diff-d0c945cc3f3dbc1f92931a90eacb84df8d6ccb60169a619700703acd8d60c5f8">+8/-4</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td> <details> <summary><strong>fortplot_tick_formatting.f90</strong><dd><code>Add mathtext delimiters to power-of-ten labels</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> src/utilities/ticks/fortplot_tick_formatting.f90 <ul><li>Wrap power-of-ten labels in mathtext delimiters (<code>$10^{n}$</code>)<br> <li> Apply formatting to both positive and negative powers</ul> </details> </td> <td><a href="https://github.com/lazy-fortran/fortplot/pull/1405/files#diff-b854d288119583f4762e92f3ee5bbc09d35ae2309e32cd9820d42cba62381ab6">+2/-2</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></td></tr><tr><td><strong>Tests</strong></td><td><table> <tr> <td> <details> <summary><strong>test_log_symlog_ticks.f90</strong><dd><code>Update test expectations for mathtext formatting</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> test/test_log_symlog_ticks.f90 <ul><li>Update expected tick labels from <code>10^{n}</code> to <code>$10^{n}$</code><br> <li> Update both positive and negative power expectations<br> <li> Maintain test logic while adjusting format expectations</ul> </details> </td> <td><a href="https://github.com/lazy-fortran/fortplot/pull/1405/files#diff-6b6eb24c38744dba8b05e680d94e05fc769b5bf8b5d110a8e7c056166e04b0bb">+10/-10</a>&nbsp; </td> </tr> <tr> <td> <details> <summary><strong>test_pdf_log_symlog_tick_positions.f90</strong><dd><code>Update PDF test for mathtext tick labels</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> test/test_pdf_log_symlog_tick_positions.f90 <ul><li>Update label comparisons to expect <code>$10^{n}$</code> format<br> <li> Remove trailing whitespace<br> <li> Maintain position verification logic</ul> </details> </td> <td><a href="https://github.com/lazy-fortran/fortplot/pull/1405/files#diff-5031fa6f40167a392d161cfc5d1f2147b10ef45ea8ce68c781e20b3d3c37ca75">+4/-5</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></td></tr></tr></tbody></table> </details> ___
1 parent 163901c commit bb7916b

File tree

4 files changed

+25
-22
lines changed

4 files changed

+25
-22
lines changed

src/ui/fortplot_axes.f90

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,18 @@ function format_tick_label(value, scale_type) result(label)
156156
character(len=*), intent(in) :: scale_type
157157
character(len=20) :: label
158158
real(wp) :: abs_value
159-
159+
logical :: is_log_scale
160+
160161
abs_value = abs(value)
161-
162-
if (abs_value < 1.0e-10_wp) then
162+
is_log_scale = trim(scale_type) == 'log' .or. trim(scale_type) == 'symlog'
163+
164+
if (abs_value <= epsilon(1.0_wp)) then
163165
label = '0'
164-
else if ((trim(scale_type) == 'log' .or. trim(scale_type) == 'symlog') .and. is_power_of_ten(value)) then
166+
else if (is_log_scale .and. is_power_of_ten(value)) then
165167
! Unify log and symlog formatting: show powers of ten with superscript
166168
label = format_power_of_ten_label(value)
169+
else if (.not. is_log_scale .and. abs_value < TICK_EPS) then
170+
label = '0'
167171
else if (abs_value >= SCIENTIFIC_THRESHOLD_HIGH .or. abs_value < SCIENTIFIC_THRESHOLD_LOW) then
168172
! Use scientific notation for very large or very small values
169173
write(label, '(ES10.2)') value

src/utilities/ticks/fortplot_tick_formatting.f90

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ function format_log_tick_value(value) result(formatted)
106106
integer :: exponent
107107
logical :: is_power_of_ten
108108

109-
if (abs(value) < 1.0e-10_wp) then
109+
if (abs(value) <= epsilon(1.0_wp)) then
110110
formatted = '0'
111111
return
112112
end if
@@ -167,9 +167,9 @@ function format_power_of_ten_label(value) result(formatted)
167167

168168
! Always emit mathtext-style powers of ten to mirror matplotlib output
169169
if (value < 0.0_wp) then
170-
write(formatted, '(A, I0, A)') '-10^{', exponent, '}'
170+
write(formatted, '(A, I0, A)') '$-10^{', exponent, '}$'
171171
else
172-
write(formatted, '(A, I0, A)') '10^{', exponent, '}'
172+
write(formatted, '(A, I0, A)') '$10^{', exponent, '}$'
173173
end if
174174
formatted = adjustl(formatted)
175175
end function format_power_of_ten_label

test/test_log_symlog_ticks.f90

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,18 @@ subroutine test_should_format_log_ticks_as_powers_of_ten()
5858
stop 1
5959
end if
6060

61-
if (trim(format_tick_label(ticks(1), 'log')) /= '10^{0}') then
62-
print *, 'FAIL: log tick at 1 should be formatted as 10^{0}'
61+
if (trim(format_tick_label(ticks(1), 'log')) /= '$10^{0}$') then
62+
print *, 'FAIL: log tick at 1 should be formatted as $10^{0}$'
6363
stop 1
6464
end if
6565

66-
if (trim(format_tick_label(ticks(2), 'log')) /= '10^{1}') then
67-
print *, 'FAIL: log tick at 10 should be formatted as 10^{1}'
66+
if (trim(format_tick_label(ticks(2), 'log')) /= '$10^{1}$') then
67+
print *, 'FAIL: log tick at 10 should be formatted as $10^{1}$'
6868
stop 1
6969
end if
7070

71-
if (trim(format_tick_label(ticks(3), 'log')) /= '10^{2}') then
72-
print *, 'FAIL: log tick at 100 should be formatted as 10^{2}'
71+
if (trim(format_tick_label(ticks(3), 'log')) /= '$10^{2}$') then
72+
print *, 'FAIL: log tick at 100 should be formatted as $10^{2}$'
7373
stop 1
7474
end if
7575
end subroutine test_should_format_log_ticks_as_powers_of_ten
@@ -114,8 +114,8 @@ subroutine test_should_include_symlog_threshold_ticks()
114114
do i = 1, num_ticks
115115
if (abs(ticks(i) + 10.0_wp) <= 1.0e-9_wp) then
116116
label = trim(format_tick_label(ticks(i), 'symlog'))
117-
if (label /= '-10^{1}') then
118-
print *, 'FAIL: symlog negative threshold should be -10^{1}, got', label
117+
if (label /= '$-10^{1}$') then
118+
print *, 'FAIL: symlog negative threshold should be $-10^{1}$, got', label
119119
stop 1
120120
end if
121121
if (found_negative_threshold) then
@@ -125,8 +125,8 @@ subroutine test_should_include_symlog_threshold_ticks()
125125
found_negative_threshold = .true.
126126
else if (abs(ticks(i) - 10.0_wp) <= 1.0e-9_wp) then
127127
label = trim(format_tick_label(ticks(i), 'symlog'))
128-
if (label /= '10^{1}') then
129-
print *, 'FAIL: symlog positive threshold should be 10^{1}, got', label
128+
if (label /= '$10^{1}$') then
129+
print *, 'FAIL: symlog positive threshold should be $10^{1}$, got', label
130130
stop 1
131131
end if
132132
if (found_positive_threshold) then

test/test_pdf_log_symlog_tick_positions.f90

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ program test_pdf_log_symlog_tick_positions
3535
if (abs(log10(yexp) - nint(log10(yexp))) < 1.0e-12_wp) then
3636
idx = -1
3737
do i = 1, ny
38-
if (trim(yl(i)) == '10^0' .and. yexp == 1.0_wp) idx = i
39-
if (trim(yl(i)) == '10^1' .and. yexp == 10.0_wp) idx = i
40-
if (trim(yl(i)) == '10^2' .and. yexp == 100.0_wp) idx = i
41-
if (trim(yl(i)) == '10^3' .and. yexp == 1000.0_wp) idx = i
38+
if (trim(yl(i)) == '$10^{0}$' .and. yexp == 1.0_wp) idx = i
39+
if (trim(yl(i)) == '$10^{1}$' .and. yexp == 10.0_wp) idx = i
40+
if (trim(yl(i)) == '$10^{2}$' .and. yexp == 100.0_wp) idx = i
41+
if (trim(yl(i)) == '$10^{3}$' .and. yexp == 1000.0_wp) idx = i
4242
end do
4343
if (idx > 0) then
4444
ymin = 1.0_wp; ymax = 1000.0_wp
@@ -79,4 +79,3 @@ program test_pdf_log_symlog_tick_positions
7979

8080
print *, 'PASS: PDF log/symlog tick positions verified'
8181
end program test_pdf_log_symlog_tick_positions
82-

0 commit comments

Comments
 (0)