diff --git a/BACKLOG.md b/BACKLOG.md index e919e5c3..67aaf0ad 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -4,17 +4,18 @@ **🚨 CRITICAL: CI test suite failures - user-visible rendering broken** +- [ ] #401: Fix - CI test-coverage failing with segfaults in colored_contours and ascii_heatmap_demo (blocks all PR merges) **🚨 CRITICAL: User-visible PNG/PDF rendering regressions** **User-Facing Issues (Medium Priority)** -- [ ] #377: Enhancement - make finer grid on pcolormesh_demo.html (enhancement) +*All user-facing issues moved to DOING* **Infrastructure & Documentation Issues (Lower Priority)** - [ ] #388: Fix - investigate test_mpeg_consolidated failure unrelated to ylabel rotation (test infrastructure) ## DOING (Current Work) -*No current work - ready for next task* +- [x] #377: Enhancement - make finer grid on pcolormesh_demo.html (branch: enhance-finer-grid-377) ## FUTURE SPRINTS - Systematic Restoration diff --git a/example/fortran/pcolormesh_demo/pcolormesh_demo.f90 b/example/fortran/pcolormesh_demo/pcolormesh_demo.f90 index 8f5be758..5a4a9bc1 100644 --- a/example/fortran/pcolormesh_demo/pcolormesh_demo.f90 +++ b/example/fortran/pcolormesh_demo/pcolormesh_demo.f90 @@ -12,29 +12,33 @@ program pcolormesh_demo contains subroutine demo_basic_gradient() - !! Basic pcolormesh with simple gradient - real(wp) :: x(6), y(5) - real(wp) :: c(4, 5) + !! Basic pcolormesh with simple gradient - enhanced 51x51 grid + real(wp) :: x(51), y(51) + real(wp) :: c(50, 50) integer :: i, j + real(wp) :: dx, dy - ! Create coordinate arrays for regular grid - do i = 1, 6 - x(i) = real(i-1, wp) * 0.4_wp + ! Create coordinate arrays for high-resolution regular grid + dx = 2.0_wp / 50.0_wp ! Total range 2.0, 50 intervals + dy = 1.2_wp / 50.0_wp ! Total range 1.2, 50 intervals + + do i = 1, 51 + x(i) = real(i-1, wp) * dx end do - do i = 1, 5 - y(i) = real(i-1, wp) * 0.3_wp + do i = 1, 51 + y(i) = real(i-1, wp) * dy end do - ! Create test data - simple gradient - do i = 1, 4 - do j = 1, 5 - c(i, j) = real(i, wp) + real(j, wp) * 0.5_wp + ! Create test data - smooth gradient across high-res grid + do i = 1, 50 + do j = 1, 50 + c(i, j) = real(i, wp) / 50.0_wp + real(j, wp) / 50.0_wp * 0.5_wp end do end do ! Create pcolormesh plot call figure(figsize=[6.4_wp, 4.8_wp]) - call title('Basic Pcolormesh - Linear Gradient') + call title('Basic Pcolormesh - Linear Gradient (50x50 resolution)') call xlabel('X coordinate') call ylabel('Y coordinate') call pcolormesh(x, y, c, colormap='viridis') @@ -45,32 +49,36 @@ subroutine demo_basic_gradient() end subroutine demo_basic_gradient subroutine demo_sinusoidal_pattern() - !! Pcolormesh with sinusoidal pattern - real(wp) :: x(9), y(9) - real(wp) :: c(8, 8) + !! Pcolormesh with sinusoidal pattern - enhanced 51x51 grid + real(wp) :: x(51), y(51) + real(wp) :: c(50, 50) real(wp) :: xi, yj integer :: i, j real(wp), parameter :: pi = 3.14159265359_wp + real(wp) :: dx, dy + + ! Create coordinate arrays for high-resolution grid + dx = 1.6_wp / 50.0_wp ! Total range 1.6, 50 intervals + dy = 1.2_wp / 50.0_wp ! Total range 1.2, 50 intervals - ! Create coordinate arrays - do i = 1, 9 - x(i) = real(i-1, wp) * 0.2_wp + do i = 1, 51 + x(i) = real(i-1, wp) * dx end do - do i = 1, 9 - y(i) = real(i-1, wp) * 0.15_wp + do i = 1, 51 + y(i) = real(i-1, wp) * dy end do - ! Create sinusoidal pattern - do i = 1, 8 - do j = 1, 8 - xi = (x(i) + x(i+1)) * 0.5_wp ! Center of quad - yj = (y(j) + y(j+1)) * 0.5_wp ! Center of quad + ! Create sinusoidal pattern with proper sampling + do i = 1, 50 + do j = 1, 50 + xi = (x(i) + x(i+1)) * 0.5_wp ! Center of cell + yj = (y(j) + y(j+1)) * 0.5_wp ! Center of cell c(i, j) = sin(2.0_wp * pi * xi) * cos(3.0_wp * pi * yj) end do end do call figure(figsize=[6.4_wp, 4.8_wp]) - call title('Pcolormesh - Sinusoidal Pattern') + call title('Pcolormesh - Sinusoidal Pattern (50x50 resolution)') call xlabel('X coordinate') call ylabel('Y coordinate') call pcolormesh(x, y, c, colormap='coolwarm') @@ -81,31 +89,37 @@ subroutine demo_sinusoidal_pattern() end subroutine demo_sinusoidal_pattern subroutine demo_different_colormaps() - !! Demo different colormaps - real(wp) :: x(6), y(6) - real(wp) :: c(5, 5) - real(wp) :: r + !! Demo different colormaps - enhanced 51x51 grid + real(wp) :: x(51), y(51) + real(wp) :: c(50, 50) + real(wp) :: r, xi, yj integer :: i, j real(wp), parameter :: pi = 3.14159265359_wp + real(wp) :: dx, dy + + ! Create coordinate arrays for high-resolution grid + dx = 1.5_wp / 50.0_wp ! Total range 1.5, 50 intervals + dy = 1.25_wp / 50.0_wp ! Total range 1.25, 50 intervals - ! Create coordinate arrays - do i = 1, 6 - x(i) = real(i-1, wp) * 0.3_wp + do i = 1, 51 + x(i) = real(i-1, wp) * dx end do - do i = 1, 6 - y(i) = real(i-1, wp) * 0.25_wp + do i = 1, 51 + y(i) = real(i-1, wp) * dy end do - ! Create radial pattern - do i = 1, 5 - do j = 1, 5 - r = sqrt((x(i) - 1.0_wp)**2 + (y(j) - 0.6_wp)**2) + ! Create radial pattern with proper sampling + do i = 1, 50 + do j = 1, 50 + xi = (x(i) + x(i+1)) * 0.5_wp ! Center of cell + yj = (y(j) + y(j+1)) * 0.5_wp ! Center of cell + r = sqrt((xi - 0.75_wp)**2 + (yj - 0.625_wp)**2) c(i, j) = exp(-r) end do end do call figure(figsize=[6.4_wp, 4.8_wp]) - call title('Pcolormesh - Radial Pattern (Plasma)') + call title('Pcolormesh - Radial Pattern (Plasma) (50x50 resolution)') call xlabel('X coordinate') call ylabel('Y coordinate') call pcolormesh(x, y, c, colormap='plasma') diff --git a/src/fortplot_matplotlib.f90 b/src/fortplot_matplotlib.f90 index 4a1596c9..0e81d64b 100644 --- a/src/fortplot_matplotlib.f90 +++ b/src/fortplot_matplotlib.f90 @@ -156,13 +156,22 @@ subroutine pcolormesh(x, y, z, shading, colormap, show_colorbar, label, & wp_linewidths = real(linewidths, wp) end if - ! Forward SUPPORTED parameters to underlying method using single call pattern - call fig%add_pcolormesh(wp_x, wp_y, wp_z, & - colormap=merge(colormap, "", present(colormap)), & - vmin=merge(wp_vmin, 0.0_wp, present(vmin)), & - vmax=merge(wp_vmax, 0.0_wp, present(vmax)), & - edgecolors=merge(wp_edgecolors, [0.0_wp, 0.0_wp, 0.0_wp], present(edgecolors)), & - linewidths=merge(wp_linewidths, 0.0_wp, present(linewidths))) + ! Forward SUPPORTED parameters to underlying method using conditional calls + if (present(colormap) .and. present(vmin) .and. present(vmax) .and. & + present(edgecolors) .and. present(linewidths)) then + call fig%add_pcolormesh(wp_x, wp_y, wp_z, & + colormap=colormap, vmin=wp_vmin, vmax=wp_vmax, & + edgecolors=wp_edgecolors, linewidths=wp_linewidths) + else if (present(colormap) .and. present(vmin) .and. present(vmax)) then + call fig%add_pcolormesh(wp_x, wp_y, wp_z, & + colormap=colormap, vmin=wp_vmin, vmax=wp_vmax) + else if (present(colormap)) then + call fig%add_pcolormesh(wp_x, wp_y, wp_z, colormap=colormap) + else if (present(vmin) .and. present(vmax)) then + call fig%add_pcolormesh(wp_x, wp_y, wp_z, vmin=wp_vmin, vmax=wp_vmax) + else + call fig%add_pcolormesh(wp_x, wp_y, wp_z) + end if deallocate(wp_x, wp_y, wp_z) end subroutine pcolormesh @@ -472,13 +481,22 @@ subroutine add_pcolormesh(x, y, z, shading, colormap, show_colorbar, label, & wp_linewidths = real(linewidths, wp) end if - ! Forward SUPPORTED parameters to underlying method using single call pattern - call fig%add_pcolormesh(wp_x, wp_y, wp_z, & - colormap=merge(colormap, "", present(colormap)), & - vmin=merge(wp_vmin, 0.0_wp, present(vmin)), & - vmax=merge(wp_vmax, 0.0_wp, present(vmax)), & - edgecolors=merge(wp_edgecolors, [0.0_wp, 0.0_wp, 0.0_wp], present(edgecolors)), & - linewidths=merge(wp_linewidths, 0.0_wp, present(linewidths))) + ! Forward SUPPORTED parameters to underlying method using conditional calls + if (present(colormap) .and. present(vmin) .and. present(vmax) .and. & + present(edgecolors) .and. present(linewidths)) then + call fig%add_pcolormesh(wp_x, wp_y, wp_z, & + colormap=colormap, vmin=wp_vmin, vmax=wp_vmax, & + edgecolors=wp_edgecolors, linewidths=wp_linewidths) + else if (present(colormap) .and. present(vmin) .and. present(vmax)) then + call fig%add_pcolormesh(wp_x, wp_y, wp_z, & + colormap=colormap, vmin=wp_vmin, vmax=wp_vmax) + else if (present(colormap)) then + call fig%add_pcolormesh(wp_x, wp_y, wp_z, colormap=colormap) + else if (present(vmin) .and. present(vmax)) then + call fig%add_pcolormesh(wp_x, wp_y, wp_z, vmin=wp_vmin, vmax=wp_vmax) + else + call fig%add_pcolormesh(wp_x, wp_y, wp_z) + end if deallocate(wp_x, wp_y, wp_z) end subroutine add_pcolormesh diff --git a/test/test_pcolormesh_enhanced_resolution.f90 b/test/test_pcolormesh_enhanced_resolution.f90 new file mode 100644 index 00000000..a61de012 --- /dev/null +++ b/test/test_pcolormesh_enhanced_resolution.f90 @@ -0,0 +1,174 @@ +program test_pcolormesh_enhanced_resolution + !! Test enhanced grid resolution for pcolormesh demo + !! Verifies that enhanced grids maintain pattern fidelity at higher resolution + + use iso_fortran_env, only: wp => real64 + use fortplot + implicit none + + logical :: test_passed + character(len=256) :: error_msg + + test_passed = .true. + error_msg = "" + + print *, "Testing enhanced resolution pcolormesh grids..." + + ! Test enhanced basic gradient + call test_enhanced_basic_gradient() + + ! Test enhanced sinusoidal pattern + call test_enhanced_sinusoidal_pattern() + + ! Test enhanced radial pattern + call test_enhanced_radial_pattern() + + if (test_passed) then + print *, "PASS: All enhanced resolution tests passed" + stop 0 + else + print *, "FAIL: ", trim(error_msg) + stop 1 + end if + +contains + + subroutine test_enhanced_basic_gradient() + !! Test enhanced basic gradient with 51x51 grid (50x50 cells) + real(wp) :: x(51), y(51), c(50, 50) + integer :: i, j, file_size + real(wp) :: dx, dy + + print *, "Testing enhanced basic gradient (50x50 cells)..." + + ! Create coordinate arrays for high-resolution grid + dx = 2.0_wp / 50.0_wp ! Total range 2.0, 50 intervals + dy = 1.2_wp / 50.0_wp ! Total range 1.2, 50 intervals + + do i = 1, 51 + x(i) = real(i-1, wp) * dx + end do + do i = 1, 51 + y(i) = real(i-1, wp) * dy + end do + + ! Create test data - smooth gradient across high-res grid + do i = 1, 50 + do j = 1, 50 + c(i, j) = real(i, wp) / 50.0_wp + real(j, wp) / 50.0_wp * 0.5_wp + end do + end do + + ! Create pcolormesh plot + call figure(figsize=[6.4_wp, 4.8_wp]) + call title('Enhanced Basic Gradient (50x50)') + call xlabel('X coordinate') + call ylabel('Y coordinate') + call pcolormesh(x, y, c, colormap='viridis') + call savefig('test_enhanced_basic_gradient.png') + + ! Verify file was created and has reasonable size + file_size = get_file_size('test_enhanced_basic_gradient.png') + if (file_size < 1000) then + test_passed = .false. + error_msg = "Enhanced basic gradient PNG too small or not created" + end if + end subroutine test_enhanced_basic_gradient + + subroutine test_enhanced_sinusoidal_pattern() + !! Test enhanced sinusoidal pattern with 51x51 grid (50x50 cells) + real(wp) :: x(51), y(51), c(50, 50) + real(wp) :: xi, yj, dx, dy + integer :: i, j, file_size + real(wp), parameter :: pi = 3.14159265359_wp + + print *, "Testing enhanced sinusoidal pattern (50x50 cells)..." + + ! Create coordinate arrays for high-resolution grid + dx = 1.6_wp / 50.0_wp ! Total range 1.6, 50 intervals + dy = 1.2_wp / 50.0_wp ! Total range 1.2, 50 intervals + + do i = 1, 51 + x(i) = real(i-1, wp) * dx + end do + do i = 1, 51 + y(i) = real(i-1, wp) * dy + end do + + ! Create sinusoidal pattern with proper sampling + do i = 1, 50 + do j = 1, 50 + xi = (x(i) + x(i+1)) * 0.5_wp ! Center of cell + yj = (y(j) + y(j+1)) * 0.5_wp ! Center of cell + c(i, j) = sin(2.0_wp * pi * xi) * cos(3.0_wp * pi * yj) + end do + end do + + call figure(figsize=[6.4_wp, 4.8_wp]) + call title('Enhanced Sinusoidal Pattern (50x50)') + call xlabel('X coordinate') + call ylabel('Y coordinate') + call pcolormesh(x, y, c, colormap='coolwarm') + call savefig('test_enhanced_sinusoidal_pattern.png') + + ! Verify file was created and has reasonable size + file_size = get_file_size('test_enhanced_sinusoidal_pattern.png') + if (file_size < 1000) then + test_passed = .false. + error_msg = "Enhanced sinusoidal pattern PNG too small or not created" + end if + end subroutine test_enhanced_sinusoidal_pattern + + subroutine test_enhanced_radial_pattern() + !! Test enhanced radial pattern with 51x51 grid (50x50 cells) + real(wp) :: x(51), y(51), c(50, 50) + real(wp) :: r, dx, dy, xi, yj + integer :: i, j, file_size + + print *, "Testing enhanced radial pattern (50x50 cells)..." + + ! Create coordinate arrays for high-resolution grid + dx = 1.5_wp / 50.0_wp ! Total range 1.5, 50 intervals + dy = 1.25_wp / 50.0_wp ! Total range 1.25, 50 intervals + + do i = 1, 51 + x(i) = real(i-1, wp) * dx + end do + do i = 1, 51 + y(i) = real(i-1, wp) * dy + end do + + ! Create radial pattern with proper sampling + do i = 1, 50 + do j = 1, 50 + xi = (x(i) + x(i+1)) * 0.5_wp ! Center of cell + yj = (y(j) + y(j+1)) * 0.5_wp ! Center of cell + r = sqrt((xi - 0.75_wp)**2 + (yj - 0.625_wp)**2) + c(i, j) = exp(-r) + end do + end do + + call figure(figsize=[6.4_wp, 4.8_wp]) + call title('Enhanced Radial Pattern (50x50)') + call xlabel('X coordinate') + call ylabel('Y coordinate') + call pcolormesh(x, y, c, colormap='plasma') + call savefig('test_enhanced_radial_pattern.png') + + ! Verify file was created and has reasonable size + file_size = get_file_size('test_enhanced_radial_pattern.png') + if (file_size < 1000) then + test_passed = .false. + error_msg = "Enhanced radial pattern PNG too small or not created" + end if + end subroutine test_enhanced_radial_pattern + + integer function get_file_size(filename) + character(len=*), intent(in) :: filename + integer(8) :: size + + inquire(file=filename, size=size) + get_file_size = int(size) + end function get_file_size + +end program test_pcolormesh_enhanced_resolution \ No newline at end of file