Skip to content

Conversation

@degzhaus
Copy link

@degzhaus degzhaus commented Oct 14, 2025

Overview

This PR adds a new scatterquiver trace type to Plotly.js for visualizing vector fields. The implementation includes:

  • New trace type: scatterquiver for quiver/vector field plots
  • Complete implementation: supplyDefaults, calc, plot, hover, and attributes
  • Comprehensive testing: Jasmine unit tests and visual regression tests
  • Mock data: Three test cases (basic, gradient, meshgrid)
  • Integration: Properly integrated into the build system

Features

  • Vector field visualization with customizable arrow scaling
  • Support for gradient fields and meshgrid data
  • Configurable arrow appearance (scale, angle, line styling)
  • Full hover support and interaction

Screenshots

Examples taken from:
https://plotly.com/python/quiver-plots/

Basic Quiver Plot

Screenshot 2025-10-14 at 9 45 48 AM

Quiver Plot with Points

Screenshot 2025-10-14 at 9 46 14 AM

Testing

  • ✅ All Jasmine unit tests passing (6/6)
  • ✅ Visual regression tests with mock data
  • ✅ Manual testing with HTML examples

Files Added/Modified

  • src/traces/scatterquiver/ - Complete trace implementation
  • lib/index.js & lib/index-strict.js - Build integration
  • test/jasmine/tests/scatterquiver_test.js - Unit tests
  • test/image/mocks/scatterquiver_*.json - Mock data
  • test/jasmine/assets/mock_lists.js - Test integration

Draft Log

  • draftlogs/7584_add.md - Changelog entry

This addresses the need for vector field visualization in Plotly.js, similar to matplotlib's quiver plots.

@degzhaus degzhaus force-pushed the degzhaus/add_scatterquiver branch 4 times, most recently from dfd3c81 to 9463b3f Compare October 19, 2025 21:12
@degzhaus
Copy link
Author

degzhaus commented Oct 19, 2025

Hello, I am new to this project and attempting to contribute my first PR.

Unfortunately, I am struggling to get the build to pass. Specifically, the publish-dist-node-v22 step:
https://app.circleci.com/pipelines/github/plotly/plotly.js/12658/workflows/ae5271e7-9971-4db1-a713-b42f0625901f/jobs/282198

I tried running npm run schema and pushing the change here:
9463b3f

But still encountering the issue.

Any insight would be greatly appreciated. Thank you!

Edit: tagging a few recent commiters for visibility, thanks so much! (cc @camdecoster @alexshoe @emilykl)

@emilykl
Copy link
Contributor

emilykl commented Oct 20, 2025

Hi @degzhaus, thank you for working on this contribution!

As it stands currently, the devtools dashboard needs to be running in order for npm run schema to work properly. So you should run npm start and leave it running, and then in another terminal run npm run schema. (@camdecoster is working on a PR to eliminate that step, see #7589)

You can also download plot-schema.json from the "Artifacts" tab in CircleCI and commit it.

@degzhaus degzhaus force-pushed the degzhaus/add_scatterquiver branch 7 times, most recently from 3a35763 to 1644aca Compare October 21, 2025 21:10
@degzhaus degzhaus force-pushed the degzhaus/add_scatterquiver branch 11 times, most recently from b07de7b to a32678d Compare October 22, 2025 03:33
@degzhaus
Copy link
Author

degzhaus commented Oct 22, 2025

Hi @degzhaus, thank you for working on this contribution!

As it stands currently, the devtools dashboard needs to be running in order for npm run schema to work properly. So you should run npm start and leave it running, and then in another terminal run npm run schema. (@camdecoster is working on a PR to eliminate that step, see #7589)

You can also download plot-schema.json from the "Artifacts" tab in CircleCI and commit it.

Thank you so much, @emilykl! That was very helpful and unblocked me.

Unfortunately, I have been struggling with the no-gl-jasmine test in ci:
https://app.circleci.com/pipelines/github/plotly/plotly.js/12700/workflows/8b80de4d-1bad-455d-baef-72bc47c31042/jobs/283463

If you have any insight, I would greatly appreciate it. Thanks again!

Edit: @emilykl i figured it out! Pardon my flailing at last night. So exciting! I have a couple of tests to add and this will be ready for review.

Thanks again for your insights and help!

@degzhaus degzhaus force-pushed the degzhaus/add_scatterquiver branch from a32678d to 76b68f6 Compare October 22, 2025 14:51
@degzhaus degzhaus force-pushed the degzhaus/add_scatterquiver branch from 64cf31d to 02c37f5 Compare October 22, 2025 15:56
@emilykl
Copy link
Contributor

emilykl commented Oct 22, 2025

@degzhaus Great news, glad you're unblocked! Thank you for your work on this. Quiver is a plot type we've gotten a lot of requests for.

A few high-level comments on the API:

  • This trace type is fairly distinct from existing scatter* trace types; let's go with the name quiver instead.

  • The most similar already-existing trace type is the 3d cone trace, so the attributes of quiver should match the existing API of cone as closely as possible for consistency. For example, rather than the scale property it should use sizemode and sizeref as the cone trace does. (Obviously, some attributes like z and w are not relevant in a 2d context).

  • Any attributes for configuring the size/scale of the arrowhead should match the arrowhead config options for annotations

    • It's also not necessary to include those options in a first version of this trace type, but any attributes that are added should be consistent with what's already in the library
  • There's a few other things I noticed in the attributes as well:

    • The scaleratio attribute doesn't belong; the scale ratio between the axes should be a property of the axes themselves, not the trace. The axis scale ratio can already be configured using the existing axis.scaleratio attribute.
    • It's unclear to me how the angle attribute interacts with u and v, since u and v are already sufficient to fully determine the arrow's angle. The angle attribute should probably be removed.

@degzhaus
Copy link
Author

@degzhaus Great news, glad you're unblocked! Thank you for your work on this. Quiver is a plot type we've gotten a lot of requests for.

A few high-level comments on the API:

  • This trace type is fairly distinct from existing scatter* trace types; let's go with the name quiver instead.

  • The most similar already-existing trace type is the 3d cone trace, so the attributes of quiver should match the existing API of cone as closely as possible for consistency. For example, rather than the scale property it should use sizemode and sizeref as the cone trace does. (Obviously, some attributes like z and w are not relevant in a 2d context).

  • Any attributes for configuring the size/scale of the arrowhead should match the arrowhead config options for annotations

    • It's also not necessary to include those options in a first version of this trace type, but any attributes that are added should be consistent with what's already in the library
  • There's a few other things I noticed in the attributes as well:

    • The scaleratio attribute doesn't belong; the scale ratio between the axes should be a property of the axes themselves, not the trace. The axis scale ratio can already be configured using the existing axis.scaleratio attribute.
    • It's unclear to me how the angle attribute interacts with u and v, since u and v are already sufficient to fully determine the arrow's angle. The angle attribute should probably be removed.

Amazing, thank you so much for taking a look and providing great guidance, Emily! Looking forward to spinning a cycle on this feedback.

@emilykl
Copy link
Contributor

emilykl commented Oct 22, 2025

@degzhaus One more comment — it would be great to include colorscale attributes in quiver so that arrows can be colored according to the magnitude of the vector. These attributes are added to the cone trace here; something similar can be done for the quiver trace. And then obviously those attributes need to be referenced in the plotting code to assign the appropriate color.

@gpdf
Copy link

gpdf commented Oct 23, 2025

@degzhaus One more comment — it would be great to include colorscale attributes in quiver so that arrows can be colored according to the magnitude of the vector. These attributes are added to the cone trace here; something similar can be done for the quiver trace. And then obviously those attributes need to be referenced in the plotting code to assign the appropriate color.

I would suggest that this be capable of using any additional attribute of the data (e.g., another parallel data series), not just the magnitude. It can be very useful to color the vectors according to some independent state variable.

@gpdf
Copy link

gpdf commented Oct 23, 2025

It's unclear to me how the angle attribute interacts with u and v, since u and v are already sufficient to fully determine the arrow's angle. The angle attribute should probably be removed.

As I understand it, the angle attribute is a single constant, not a data array. I believe it's not an angle for the direction that the arrow points - as you say that's determined by the u and v data arrays - but rather the "sharpness" of the arrowhead.

I think it was directly copied from Plotly.py's figure_factor.create_quiver().

This is how it came to be in this PR; that doesn't mean that a better solution might not be to use the standard arrowhead-styling options mentioned in another comment.

},
scale: {
valType: 'number',
dflt: 0.1,
Copy link

Choose a reason for hiding this comment

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

This is my only concern not already mentioned in others' comments; it's not clear that a default of 0.1 doesn't violate the "principle of least surprise".

Again I think this was copied verbatim from Plotly.py's figure_factory.create_quiver but it may be worth reviewing whether it's really the right choice.

@emilykl
Copy link
Contributor

emilykl commented Oct 23, 2025

It's unclear to me how the angle attribute interacts with u and v, since u and v are already sufficient to fully determine the arrow's angle. The angle attribute should probably be removed.

As I understand it, the angle attribute is a single constant, not a data array. I believe it's not an angle for the direction that the arrow points - as you say that's determined by the u and v data arrays - but rather the "sharpness" of the arrowhead.

I think it was directly copied from Plotly.py's figure_factor.create_quiver().

This is how it came to be in this PR; that doesn't mean that a better solution might not be to use the standard arrowhead-styling options mentioned in another comment.

@gpdf Ah! Yes, that seems right according to the code, thanks for the correction.

But yeah, in cases where the Plotly.py figure_factory API conflicts with the Plotly.js API, it's more important to be consistent with the rest of Plotly.js. So we should ideally use the existing arrowhead API here.

@gpdf
Copy link

gpdf commented Oct 24, 2025

@emilykl Would it be "Plotlyesque" for there to be an option to show arrows as "o------" as a selectable alternative to "------>"? That is, instead of a line at the start and an arrowhead at the end, a dot at the start and a bare line at the end? I've tried reading the existing arrow documentation and I'm not entirely clear whether this is currently part of the Plotly.js API.

@emilykl
Copy link
Contributor

emilykl commented Oct 24, 2025

@emilykl Would it be "Plotlyesque" for there to be an option to show arrows as "o------" as a selectable alternative to "------>"? That is, instead of a line at the start and an arrowhead at the end, a dot at the start and a bare line at the end? I've tried reading the existing arrow documentation and I'm not entirely clear whether this is currently part of the Plotly.js API.

@gpdf The arrowhead attributes are poorly documented, but this is possible using the existing API — for an annotation, you can set arrowside: 'start' to show an arrowhead only at the start of the line, and startarrowhead: 6 to make it shaped like a dot.

Codepen here

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants