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

metrics: separate default settings from override #5030

Merged
merged 2 commits into from
Jun 2, 2021

Conversation

stephanwlee
Copy link
Contributor

Background: currently, from view's and deep linker's perspective, there
is no way to discern a setting that was overridden vs. default. This
makes the deep linking particularly finicky since, if a different
application provides a different default for smoothing, for example, it
will show up in the deep link as it does not match OSS's default 0.6.

Change: this change separates default away from overrides while making
it largely transparent to views.

Background: currently, from view's and deep linker's perspective, there
is no way to discern a setting that was overridden vs. default. This
makes the deep linking particularly finicky since, if a different
application provides a different default for smoothing, for example, it
will show up in the deep link as it does not match OSS's default 0.6.

Change: this change separates default away from overrides while making
it largely transparent to views.
@stephanwlee stephanwlee requested a review from psybuzz June 1, 2021 21:23
@google-cla google-cla bot added the cla: yes label Jun 1, 2021
imageContrastInMilli: contrastInMilli,
},
};
}),
on(actions.metricsResetImageBrightness, (state) => {
const settingOverrides = {...state.settingOverrides};
delete settingOverrides['imageBrightnessInMilli'];
Copy link
Contributor

Choose a reason for hiding this comment

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

Double checking, does this work with property renaming, or do we need the 'declare' keyword on export interface MetricsSettings, similar to other interfaces we protect?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, you are correct. I do not intend to use declare just for sake of the delete so I worked around it.
I meant to test this before mailing this change out but I have forgotten it.

In my test:

interface IFoo {
  apple: number;
  banana: number;
};
const foo: Partial<IFoo> = {
  apple: 1,
  banana: 2
};

function Foo(foo: Partial<IFoo>) {
  delete foo['apple'];
  console.log(foo);
}

Foo(foo);
// built
var a={g:1,h:2};delete a.apple;console.log(a);

JSCompiler is unable to understand delete and the property name here.

);

/**
* Settings.
*/
export const getMetricsSettingOverrides = createSelector(
selectMetricsState,
(state): MetricsState['settingOverrides'] => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think Partial<MetricsSettings> as the return type would be more readable, to not require a jump to definition here.

return [{key: SMOOTHING_KEY, value: String(smoothing)}];
store.select(selectors.getMetricsSettingOverrides).pipe(
map((settingOverrides) => {
if (Number.isFinite(settingOverrides.scalarSmoothing)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

scalarSmoothing is never infinite, is it? Is a typeof settingOverrides.scalarSmoothing === 'undefined' sufficient?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

While you are correct that I am abusing the Number.isFinite(undefined), I am also using it for Number.isFinite(NaN) === false)

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. Then separately, I think it would be better if metrics_reducer would be responsible for discarding NaNs, so that store-readers would not have to do this isFinite check. Right now, the settings pane does not do this check when using the selector.

@stephanwlee stephanwlee merged commit da66ad4 into tensorflow:master Jun 2, 2021
@stephanwlee stephanwlee deleted the smoothing branch June 2, 2021 16:48
stephanwlee added a commit to stephanwlee/tensorboard that referenced this pull request Dec 11, 2021
PR tensorflow#5030 divided up the default setting from overrides and, in selector,
we have mixed two values in selectors to make a concrete settings value.

When reset, overriden values were set to `undefined` and caused the
settings to be very wrong.

```ts
// This resolves to {a: undefined}
{...{a: 1}, ...{a: undefined}}
```

Object spread (or `assign`) does not skip a property whose value is
`undefined` and causes settingOverride with undefined value to take
precedence over the default value which, in the end, resolves the image
brightness/contrast values to `undefined` unlike what the types
indicated.

In the end, this is a fault of the type system since the interface is
defined as `Partial<>` and a value should really not have `undefined`
value. To illustrate,

```ts
interface Foo {
  bar: number;
}

// Legal; `bar` property may not exist
const foo2: Partial<Foo> = {
};

// Legal; `bar` is defined as `number` but here, it is `undefined`
// yet it is legal.
const foo3: Partial<Foo> = {
  bar: undefined
};
```

TypeScript 4.4 has a way to property guard against `undefined` value in
a `Partial<>` type, `"exactOptionalPropertyTypes"` but TensorBoard app
currently violates the type definition so we will enable the tsconfig in
a subsequent changes.
stephanwlee added a commit that referenced this pull request Dec 14, 2021
PR #5030 divided up the default setting from overrides and, in selector,
we have mixed two values in selectors to make a concrete settings value.

When reset, overriden values were set to `undefined` and caused the
settings to be very wrong.

```ts
// This resolves to {a: undefined}
{...{a: 1}, ...{a: undefined}}
```

Object spread (or `assign`) does not skip a property whose value is
`undefined` and causes settingOverride with undefined value to take
precedence over the default value which, in the end, resolves the image
brightness/contrast values to `undefined` unlike what the types
indicated.

In the end, this is a fault of the type system since the interface is
defined as `Partial<>` and a value should really not have `undefined`
value. To illustrate,

```ts
interface Foo {
  bar: number;
}

// Legal; `bar` property may not exist
const foo2: Partial<Foo> = {
};

// Legal; `bar` is defined as `number` but here, it is `undefined`
// yet it is legal.
const foo3: Partial<Foo> = {
  bar: undefined
};
```

TypeScript 4.4 has a way to property guard against `undefined` value in
a `Partial<>` type, `"exactOptionalPropertyTypes"` but TensorBoard app
currently violates the type definition so we will enable the tsconfig in
a subsequent changes.
yatbear pushed a commit to yatbear/tensorboard that referenced this pull request Mar 27, 2023
PR tensorflow#5030 divided up the default setting from overrides and, in selector,
we have mixed two values in selectors to make a concrete settings value.

When reset, overriden values were set to `undefined` and caused the
settings to be very wrong.

```ts
// This resolves to {a: undefined}
{...{a: 1}, ...{a: undefined}}
```

Object spread (or `assign`) does not skip a property whose value is
`undefined` and causes settingOverride with undefined value to take
precedence over the default value which, in the end, resolves the image
brightness/contrast values to `undefined` unlike what the types
indicated.

In the end, this is a fault of the type system since the interface is
defined as `Partial<>` and a value should really not have `undefined`
value. To illustrate,

```ts
interface Foo {
  bar: number;
}

// Legal; `bar` property may not exist
const foo2: Partial<Foo> = {
};

// Legal; `bar` is defined as `number` but here, it is `undefined`
// yet it is legal.
const foo3: Partial<Foo> = {
  bar: undefined
};
```

TypeScript 4.4 has a way to property guard against `undefined` value in
a `Partial<>` type, `"exactOptionalPropertyTypes"` but TensorBoard app
currently violates the type definition so we will enable the tsconfig in
a subsequent changes.
dna2github pushed a commit to dna2fork/tensorboard that referenced this pull request May 1, 2023
PR tensorflow#5030 divided up the default setting from overrides and, in selector,
we have mixed two values in selectors to make a concrete settings value.

When reset, overriden values were set to `undefined` and caused the
settings to be very wrong.

```ts
// This resolves to {a: undefined}
{...{a: 1}, ...{a: undefined}}
```

Object spread (or `assign`) does not skip a property whose value is
`undefined` and causes settingOverride with undefined value to take
precedence over the default value which, in the end, resolves the image
brightness/contrast values to `undefined` unlike what the types
indicated.

In the end, this is a fault of the type system since the interface is
defined as `Partial<>` and a value should really not have `undefined`
value. To illustrate,

```ts
interface Foo {
  bar: number;
}

// Legal; `bar` property may not exist
const foo2: Partial<Foo> = {
};

// Legal; `bar` is defined as `number` but here, it is `undefined`
// yet it is legal.
const foo3: Partial<Foo> = {
  bar: undefined
};
```

TypeScript 4.4 has a way to property guard against `undefined` value in
a `Partial<>` type, `"exactOptionalPropertyTypes"` but TensorBoard app
currently violates the type definition so we will enable the tsconfig in
a subsequent changes.
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.

2 participants