Skip to content

Commit d4338ea

Browse files
JamesHollyeryatbear
authored andcommitted
Step Selector: Add smoothed column in data table when enabled (#5839)
Motivation for features / changes This change adds the "Smoothed" column to the data table which we expect users to want. It also helps align the data table more closely with the tooltip. Technical description of changes Since this column is more dynamic and should only appear when smoothing is enabled I moved the dataHeaders construction to the container where I made it dependent on the smoothingEnabled$ Observable.
1 parent 682c93f commit d4338ea

File tree

5 files changed

+89
-6
lines changed

5 files changed

+89
-6
lines changed

tensorboard/webapp/metrics/views/card_renderer/scalar_card_component.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export class ScalarCardComponent<Downloader> {
9292
@Input() linkedTimeSelection!: TimeSelectionView | null;
9393
@Input() stepSelectorTimeSelection!: TimeSelection;
9494
@Input() minMaxStep!: MinMaxStep;
95+
@Input() dataHeaders!: ColumnHeaders[];
9596

9697
@Output() onFullSizeToggle = new EventEmitter<void>();
9798
@Output() onPinClicked = new EventEmitter<boolean>();
@@ -116,12 +117,6 @@ export class ScalarCardComponent<Downloader> {
116117

117118
yScaleType = ScaleType.LINEAR;
118119
isViewBoxOverridden: boolean = false;
119-
dataHeaders: ColumnHeaders[] = [
120-
ColumnHeaders.RUN,
121-
ColumnHeaders.VALUE,
122-
ColumnHeaders.STEP,
123-
ColumnHeaders.RELATIVE_TIME,
124-
];
125120

126121
toggleYScaleType() {
127122
this.yScaleType =
@@ -269,6 +264,9 @@ export class ScalarCardComponent<Downloader> {
269264
selectedStepData.RELATIVE_TIME =
270265
closestStartPoint.relativeTimeInMs;
271266
continue;
267+
case ColumnHeaders.SMOOTHED:
268+
selectedStepData.SMOOTHED = closestStartPoint.y;
269+
continue;
272270
default:
273271
continue;
274272
}

tensorboard/webapp/metrics/views/card_renderer/scalar_card_container.ts

+18
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ import {CardRenderer} from '../metrics_view_types';
8181
import {getTagDisplayName} from '../utils';
8282
import {DataDownloadDialogContainer} from './data_download_dialog_container';
8383
import {
84+
ColumnHeaders,
8485
MinMaxStep,
8586
PartialSeries,
8687
PartitionedSeries,
@@ -145,6 +146,7 @@ function areSeriesEqual(
145146
[stepSelectorTimeSelection]="stepSelectorTimeSelection$ | async"
146147
[forceSvg]="forceSvg$ | async"
147148
[minMaxStep]="minMaxSteps$ | async"
149+
[dataHeaders]="columnHeaders$ | async"
148150
(onFullSizeToggle)="onFullSizeToggle()"
149151
(onPinClicked)="pinStateChanged.emit($event)"
150152
observeIntersection
@@ -191,6 +193,7 @@ export class ScalarCardContainer implements CardRenderer, OnInit, OnDestroy {
191193
linkedTimeSelection$?: Observable<TimeSelectionView | null>;
192194
stepSelectorTimeSelection$?: Observable<TimeSelection | null>;
193195
minMaxSteps$?: Observable<MinMaxStep>;
196+
columnHeaders$?: Observable<ColumnHeaders[]>;
194197

195198
onVisibilityChange({visible}: {visible: boolean}) {
196199
this.isVisible = visible;
@@ -353,6 +356,21 @@ export class ScalarCardContainer implements CardRenderer, OnInit, OnDestroy {
353356
})
354357
);
355358

359+
this.columnHeaders$ = this.smoothingEnabled$.pipe(
360+
map((smoothingEnabled) => {
361+
const headers = [
362+
ColumnHeaders.RUN,
363+
ColumnHeaders.VALUE,
364+
ColumnHeaders.STEP,
365+
ColumnHeaders.RELATIVE_TIME,
366+
];
367+
if (smoothingEnabled) {
368+
headers.splice(1, 0, ColumnHeaders.SMOOTHED);
369+
}
370+
return headers;
371+
})
372+
);
373+
356374
this.dataSeries$ = partitionedSeries$.pipe(
357375
// Smooth
358376
combineLatestWith(this.store.select(getMetricsScalarSmoothing)),

tensorboard/webapp/metrics/views/card_renderer/scalar_card_test.ts

+57
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ import {ScalarCardComponent} from './scalar_card_component';
9696
import {ScalarCardContainer} from './scalar_card_container';
9797
import {ScalarCardFobController} from './scalar_card_fob_controller';
9898
import {
99+
ColumnHeaders,
99100
ScalarCardPoint,
100101
ScalarCardSeriesMetadata,
101102
SeriesType,
@@ -2651,6 +2652,62 @@ describe('scalar card', () => {
26512652
expect(data[0].RUN).toEqual('100 test alias 1/Run1 name');
26522653
expect(data[1].RUN).toEqual('200 test alias 2/Run2 name');
26532654
}));
2655+
2656+
it('adds smoothed column header when smoothed is enabled', fakeAsync(() => {
2657+
store.overrideSelector(selectors.getMetricsScalarSmoothing, 0.8);
2658+
2659+
const runToSeries = {
2660+
run1: [
2661+
{wallTime: 1, value: 1, step: 10},
2662+
{wallTime: 2, value: 10, step: 20},
2663+
{wallTime: 3, value: 20, step: 35},
2664+
],
2665+
};
2666+
provideMockCardRunToSeriesData(
2667+
selectSpy,
2668+
PluginType.SCALARS,
2669+
'card1',
2670+
null /* metadataOverride */,
2671+
runToSeries
2672+
);
2673+
store.overrideSelector(
2674+
selectors.getCurrentRouteRunSelection,
2675+
new Map([['run1', true]])
2676+
);
2677+
store.overrideSelector(getMetricsLinkedTimeSelection, {
2678+
start: {step: 20},
2679+
end: null,
2680+
});
2681+
2682+
const fixture = createComponent('card1');
2683+
fixture.detectChanges();
2684+
const scalarCardComponent = fixture.debugElement.query(
2685+
By.directive(ScalarCardComponent)
2686+
);
2687+
2688+
expect(scalarCardComponent.componentInstance.dataHeaders).toContain(
2689+
ColumnHeaders.SMOOTHED
2690+
);
2691+
2692+
expect(
2693+
scalarCardComponent.componentInstance.getTimeSelectionTableData()[0]
2694+
.SMOOTHED
2695+
).toBe(6.000000000000001);
2696+
}));
2697+
2698+
it('does not add smoothed column header when smoothed is disabled', fakeAsync(() => {
2699+
store.overrideSelector(selectors.getMetricsScalarSmoothing, 0);
2700+
2701+
const fixture = createComponent('card1');
2702+
fixture.detectChanges();
2703+
const scalarCardComponent = fixture.debugElement.query(
2704+
By.directive(ScalarCardComponent)
2705+
);
2706+
2707+
expect(scalarCardComponent.componentInstance.dataHeaders).not.toContain(
2708+
ColumnHeaders.SMOOTHED
2709+
);
2710+
}));
26542711
});
26552712

26562713
describe('step selector feature integration', () => {

tensorboard/webapp/metrics/views/card_renderer/scalar_card_types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export enum ColumnHeaders {
8383
STEP = 'STEP',
8484
TIME = 'TIME',
8585
VALUE = 'VALUE',
86+
SMOOTHED = 'SMOOTHED',
8687
}
8788

8889
/**

tensorboard/webapp/widgets/data_table/data_table_component.ts

+9
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ export class DataTableComponent {
4848
return 'Time';
4949
case ColumnHeaders.RELATIVE_TIME:
5050
return 'Relative';
51+
case ColumnHeaders.SMOOTHED:
52+
return 'Smoothed';
5153
default:
5254
return '';
5355
}
@@ -88,6 +90,13 @@ export class DataTableComponent {
8890
return relativeTimeFormatter.formatReadable(
8991
selectedStepRunData.RELATIVE_TIME as number
9092
);
93+
case ColumnHeaders.SMOOTHED:
94+
if (selectedStepRunData.SMOOTHED === undefined) {
95+
return '';
96+
}
97+
return numberFormatter.formatShort(
98+
selectedStepRunData.SMOOTHED as number
99+
);
91100
default:
92101
return '';
93102
}

0 commit comments

Comments
 (0)