Skip to content
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

line chart: draw NaN with triangle #4461

Merged
merged 3 commits into from
Dec 15, 2020

Conversation

stephanwlee
Copy link
Contributor

This change adds the feature of vz-line-chart of rendering null values
as triangles.

Business logic:

  • for non-first NaNs: carry the y value from the last non-NaN value
  • for starting NaNs with non-NaN values in the series: assign y values
    from the first non-NaN value.
  • for all NaNs: assign 0 to y.

] of partitionedPolyline.entries()) {
if (type === PartitionType.NUMBER) {
if (polyline.length === 2) {
if (metadata.aux) continue;
Copy link
Contributor

Choose a reason for hiding this comment

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

iiuc, this is saying we want to skip drawing the circle because:

  • An aux series cannot be drawn alone without a corresponding non-aux series in the same view
  • A single-point aux and non-aux series will want a circle at the exact same position

If these are the only reasons why we can skip, I'm not sure we should do so in SeriesLineView. These 2 assumptions are really true only in this scalar card scenario where "aux" represents smoothing. To keep SeriesLineView agnostic, should we drop this check?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree that it has leaky abstraction and ideally, we should make NaN drawing a feature specified in the metadata but I do not yet see a strong reason to do so.

Few things though (since there seems to be some confusion).

  • aux is the original series (shown in faded color) when smoothing is enabled
  • vz_line_chart did not show NaNs for aux/original-series and I am merely trying to have the same UX.

vz_line_chart
image

Gpu line chart
image

Again, we are kind of are abusing the aux flag but I think there is a balance between flags for every feature vs. simplicity. I expect the API to naturally evolve as we adopt the line chart in more use cases.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, I think I see where you are coming from. By making SeriesLineView aware of the fact that aux lines never draw NaNs, we gain a good amount of simplicity. I think this is reasonable, and keeping L135-136 is fine with me.

However, I don't agree in the number case (non-NaN). Shouldn't all (non-NaN) lines be drawn the same way, whether they are aux or not? If we treat aux+nonNaN the same as nonAux+nonNan, I think we satisfy those goals:

aux is the original series (shown in faded color) when smoothing is enabled
vz_line_chart did not show NaNs for aux/original-series and I am merely trying to have the same UX.

Concretely, I think dropping L111 changes our cases from this:
If line segment is [number && singlePoint && aux] skip
If line segment is [number && non-aux] draw
If line segment is [NaN && aux] skip
If line segment is [NaN && non-aux] draw

Into this:
If line segment is [number] draw
If line segment is [NaN && aux] skip
If line segment is [NaN && non-aux] draw

Is there something we gain by keeping L111, besides rendering fewer points in the single point scenario, that I might be missing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, got it. I simply decided not to draw the circle for aux because there was no circle for single point in vz_line_chart at all!

I took your advise and remove L111.

): Array<{polyline: Float32Array; type: PartitionType}> {
if (polyline.length % 2 !== 0) {
throw new Error(`Cannot have odd length-ed polyline: ${polyline.length}`);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I would slightly prefer moving this check closer to the place where the polyline is constructed, or perhaps even better to remove it entirely. Polylines type has a nice comment "Flattened array of 2d coordinates...", and it would be a bit cumbersome to have to require all consumers to check the even-ness of it, imo.

Another idea is to rename Polyline to Polyline2D or something that readers and users of it would instantly know that it's safe to assume that it is even.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Leaning not making the change. We have plenty of those invariant checks but as a dev who jumps around a lot, I think it makes sense to have the same invariant in multiple places if it is not type checkable since it makes reading the code much easier.

Copy link
Contributor

Choose a reason for hiding this comment

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

In that case, can we move this check to the calling function redraw() ~L103? Its function body relies on the invariant (in the loop around L137), so having the check there helps me realize that everything in redraw() operates with the validated assumption.

This change adds the feature of vz-line-chart of rendering null values
as triangles.

Business logic:
- for non-first NaNs: carry the y value from the last non-NaN value
- for starting NaNs with non-NaN values in the series: assign y values
  from the first non-NaN value.
- for all NaNs: assign 0 to y.
Copy link
Contributor

@psybuzz psybuzz left a comment

Choose a reason for hiding this comment

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

Overall looks good

): Array<{polyline: Float32Array; type: PartitionType}> {
if (polyline.length % 2 !== 0) {
throw new Error(`Cannot have odd length-ed polyline: ${polyline.length}`);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

In that case, can we move this check to the calling function redraw() ~L103? Its function body relies on the invariant (in the loop around L137), so having the check there helps me realize that everything in redraw() operates with the validated assumption.

] of partitionedPolyline.entries()) {
if (type === PartitionType.NUMBER) {
if (polyline.length === 2) {
if (metadata.aux) continue;
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, I think I see where you are coming from. By making SeriesLineView aware of the fact that aux lines never draw NaNs, we gain a good amount of simplicity. I think this is reasonable, and keeping L135-136 is fine with me.

However, I don't agree in the number case (non-NaN). Shouldn't all (non-NaN) lines be drawn the same way, whether they are aux or not? If we treat aux+nonNaN the same as nonAux+nonNan, I think we satisfy those goals:

aux is the original series (shown in faded color) when smoothing is enabled
vz_line_chart did not show NaNs for aux/original-series and I am merely trying to have the same UX.

Concretely, I think dropping L111 changes our cases from this:
If line segment is [number && singlePoint && aux] skip
If line segment is [number && non-aux] draw
If line segment is [NaN && aux] skip
If line segment is [NaN && non-aux] draw

Into this:
If line segment is [number] draw
If line segment is [NaN && aux] skip
If line segment is [NaN && non-aux] draw

Is there something we gain by keeping L111, besides rendering fewer points in the single point scenario, that I might be missing?

Copy link
Contributor

@psybuzz psybuzz left a comment

Choose a reason for hiding this comment

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

Thanks for the changes, lgtm!

@stephanwlee stephanwlee merged commit aa8dbfd into tensorflow:master Dec 15, 2020
@stephanwlee stephanwlee deleted the lc_draw_null branch December 15, 2020 05:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants