Skip to content

[graph] Do not abort scatter painting loop on non-positive log coordinates (fixes #23833) - #23834

Open
muntasir-396 wants to merge 3 commits into
root-project:masterfrom
muntasir-396:fix/scatter-log-break
Open

muntasir-396 wants to merge 3 commits into
root-project:masterfrom
muntasir-396:fix/scatter-log-break

Conversation

@muntasir-396

Copy link
Copy Markdown
Contributor

Summary

When plotting a TScatter or TScatter2D on a pad with logarithmic scale enabled (gPad->SetLogx(), SetLogy(), or SetLogz()), encountering any non-positive coordinate (x <= 0, y <= 0, or z <= 0) caused TGraphPainter::PaintScatter and PaintScatter2D to terminate the entire rendering loop via else break;.

As a consequence, if an early point in the array happened to be non-positive, all subsequent valid positive points were omitted from the canvas.

Changes

  • In TGraphPainter::PaintScatter and PaintScatter2D, replaced else break; with else continue; in logx, logy, and logz marker loops.
  • Added regression unit tests in hist/hist/test/test_TScatter_Log.cxx testing TScatter and TScatter2D with non-positive points under logarithmic scales.

Fixes #23833.

…nates (fixes root-project#23833)

- In TGraphPainter::PaintScatter and PaintScatter2D, replace 'else break;'
  with 'else continue;' in the log scale coordinate checks.
- Ensures that non-positive coordinates (x, y, or z <= 0) on logarithmic
  axes are skipped individually without aborting the rendering of all
  subsequent valid positive markers.
- Add regression unit tests in hist/hist/test/test_TScatter_Log.cxx.

@ferdymercury ferdymercury left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the same issue appear with TH2D drawn with COLZ with logz?
Thks

@muntasir-396

Copy link
Copy Markdown
Contributor Author

Hi @ferdymercury

Thanks for the review!

I checked THistPainter::PaintColorLevels and PaintColorLevelsFast for TH2D histograms drawn with COLZ and logz. The issue doesn’t seem to occur there. THistPainter handles non-positive bins correctly using continue; and clamping (z = z > 0 ? TMath::Log10(z) : zmin;), so the loop continues instead of stopping early, and all bins are painted as expected.

The premature else break; issue was specific to the marker loops in TGraphPainter::PaintScatter and PaintScatter2D.

@dpiparo dpiparo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR. Could you please address the comments so that we can start the integration process?

Comment thread hist/hist/test/CMakeLists.txt Outdated
ROOT_ADD_GTEST(test_th1d_tpad_buildlegend test_th1d_tpad_buildlegend.cxx LIBRARIES Hist Gpad)

# Test for https://github.com/root-project/root/issues/23833
ROOT_ADD_GTEST(test_TScatter_Log test_TScatter_Log.cxx LIBRARIES Hist Gpad Graf Core)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we call this test_tscatter and test_tscatter.cxx?

Comment thread hist/hist/test/test_TScatter_Log.cxx Outdated
TEST(TScatterLog, NonPositivePointsInLogScale)
{
gROOT->SetBatch(true);
auto c = new TCanvas("c_scatter_log", "c_scatter_log", 800, 600);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we put this on the stack?

Comment thread hist/hist/test/test_TScatter_Log.cxx Outdated
Comment thread hist/hist/test/test_TScatter_Log.cxx Outdated
TEST(TScatter2DLog, NonPositivePointsInLogScale)
{
gROOT->SetBatch(true);
auto c = new TCanvas("c_scatter2d_log", "c_scatter2d_log", 800, 600);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, on the stack

Comment thread hist/hist/test/test_TScatter_Log.cxx Outdated
double col[n] = {1.0, 2.0, 3.0, 4.0, 5.0};
double size[n] = {2.0, 2.0, 2.0, 2.0, 2.0};

auto scatter2d = new TScatter2D(n, x, y, z, col, size);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, on the stack

@dpiparo

dpiparo commented Oct 25, 2026

Copy link
Copy Markdown
Member

@muntasir-396

Copy link
Copy Markdown
Contributor Author

Yes @dpiparo ,, I used an AI assistant to help draft the issue description, reproducer macro, and PR text, in compliance with the disclosure policy.

I have reviewed and verified the underlying C++ fix in TGraphPainter.cxx (replacing else break; with else continue; so non-positive points in log scale don't prematurely abort the rendering loop).

I have also addressed your review comments:

  1. Renamed the test file and CMake target to test_tscatter.
  2. Changed all test objects (TCanvas, TScatter, TScatter2D) to be allocated on the stack instead of using new.

The updated commit has been pushed to the branch. Thank you for the guidance!

@dpiparo

dpiparo commented Oct 25, 2026

Copy link
Copy Markdown
Member

thanks. Let's how the tests go.

@muntasir-396

Copy link
Copy Markdown
Contributor Author

Updated in commit 0c65f14:

  • Formatted hist/histpainter/src/TGraphPainter.cxx with git-clang-format to strictly follow ROOT's clang-format conventions.
  • Set the Z-axis range on TScatter in test_tscatter.cxx (scatter.GetZaxis()->SetRangeUser(1.0, 5.0)) so the underlying palette histogram validation in PaintScatter passes cleanly without diagnostics.

Also note: the earlier clang-format CI check failure was caused by apt.llvm.org returning 404 for Ubuntu 26.04 (resolute) in llvm.sh 20 on GitHub's ubuntu-latest runner. Pinning runs-on: ubuntu-24.04 in .github/workflows/code_analysis.yml upstream avoids that runner issue.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[graph] TScatter / TScatter2D stops drawing remaining points if a non-positive value is encountered in log scale

3 participants