diff --git a/tensorboard/backend/application_test.py b/tensorboard/backend/application_test.py index 9865838627..a96ce478b9 100644 --- a/tensorboard/backend/application_test.py +++ b/tensorboard/backend/application_test.py @@ -182,7 +182,6 @@ def testPluginsListing(self): 'remove_dom': False, 'tab_name': 'foo', 'disable_reload': False, - 'use_data_selector': False, }, 'bar': { 'enabled': False, @@ -193,7 +192,6 @@ def testPluginsListing(self): 'tab_name': 'bar', 'remove_dom': False, 'disable_reload': False, - 'use_data_selector': False, }, 'baz': { 'enabled': True, @@ -204,7 +202,6 @@ def testPluginsListing(self): 'tab_name': 'baz', 'remove_dom': False, 'disable_reload': False, - 'use_data_selector': False, }, } ) @@ -269,7 +266,6 @@ def testPluginsListing(self): 'remove_dom': False, 'tab_name': 'foo', 'disable_reload': False, - 'use_data_selector': False, }, 'bar': { 'enabled': False, @@ -280,7 +276,6 @@ def testPluginsListing(self): 'tab_name': 'bar', 'remove_dom': False, 'disable_reload': False, - 'use_data_selector': False, }, 'baz': { 'enabled': True, @@ -291,7 +286,6 @@ def testPluginsListing(self): 'tab_name': 'baz', 'remove_dom': False, 'disable_reload': False, - 'use_data_selector': False, }, } ) diff --git a/tensorboard/components/tf_categorization_utils/BUILD b/tensorboard/components/tf_categorization_utils/BUILD index 6c0b35e82f..ea1fa05874 100644 --- a/tensorboard/components/tf_categorization_utils/BUILD +++ b/tensorboard/components/tf_categorization_utils/BUILD @@ -18,7 +18,6 @@ tf_web_library( deps = [ "//tensorboard/components/tf_backend", "//tensorboard/components/tf_dashboard_common", - "//tensorboard/components/tf_data_selector:type", "//tensorboard/components/tf_imports:lodash", "//tensorboard/components/tf_imports:polymer", "//tensorboard/components/tf_storage", diff --git a/tensorboard/components/tf_categorization_utils/categorizationUtils.ts b/tensorboard/components/tf_categorization_utils/categorizationUtils.ts index 7575e60206..0520d2c35d 100644 --- a/tensorboard/components/tf_categorization_utils/categorizationUtils.ts +++ b/tensorboard/components/tf_categorization_utils/categorizationUtils.ts @@ -138,87 +138,6 @@ export function categorizeTags( })); } -/** - * Creates grouping of the data based on selection from tf-data-selector. It - * groups data by prefixes of tag names and by tag names. Each group contains - * series, a tuple of experiment name and run name. - */ -export function categorizeSelection( - selection: tf_data_selector.Selection[], pluginName: string): - SeriesCategory[] { - const tagToSeries = new Map(); - // `tagToSearchSeries` contains subset of `tagToSeries`. tagRegex in each - // selection can omit series from a tag category. - const tagToSearchSeries = new Map(); - const searchCategories = []; - - selection.forEach(({experiment, runs, tagRegex}) => { - const runNames = runs.map(({name}) => name); - const selectedRunToTag = createRunToTagForPlugin(runs, pluginName); - const tagToSelectedRuns = createTagToRuns(selectedRunToTag); - const tags = tf_backend.getTags(selectedRunToTag); - // list of all tags that has selected runs. - tags.forEach(tag => { - const series = tagToSeries.get(tag) || []; - series.push(...tagToSelectedRuns.get(tag) - .map(run => ({experiment, run, tag}))); - tagToSeries.set(tag, series); - }); - - const searchCategory = categorizeBySearchQuery(tags, tagRegex); - searchCategories.push(searchCategory); - // list of tags matching tagRegex in the selection. - searchCategory.items.forEach(tag => { - const series = tagToSearchSeries.get(tag) || []; - series.push(...tagToSelectedRuns.get(tag) - .map(run => ({experiment, run, tag}))); - tagToSearchSeries.set(tag, series); - }); - }); - - const searchCategory: RawCategory = searchCategories.length == 1 ? - searchCategories[0] : - { - name: searchCategories.every(c => !c.name) ? '' : 'multi', - metadata: { - type: CategoryType.SEARCH_RESULTS, - compositeSearch: true, - validRegex: searchCategories.every(c => c.metadata.validRegex), - universalRegex: false, - }, - items: Array.from(tagToSearchSeries.keys()) - .sort(vz_sorting.compareTagNames), - }; - - const searchSeriesCategory: SeriesCategory = Object.assign( - {}, - searchCategory, - { - items: searchCategory.items.map(tag => ({ - tag, - series: tagToSearchSeries.get(tag), - })), - }, - ); - - // Organize the tag to items by prefix. - const prefixCategories: SeriesCategory[] = categorizeByPrefix( - Array.from(tagToSeries.keys())) - .map(({name, metadata, items}) => ({ - name, - metadata, - items: items.map(tag => ({ - tag, - series: tagToSeries.get(tag), - })), - })); - - return [ - searchSeriesCategory, - ...prefixCategories, - ]; -} - function createTagToRuns(runToTag: RunToTag): Map { const tagToRun = new Map(); Object.keys(runToTag).forEach(run => { diff --git a/tensorboard/components/tf_categorization_utils/test/categorizationUtilsTests.ts b/tensorboard/components/tf_categorization_utils/test/categorizationUtilsTests.ts index 1b133d0aab..3bd41b0041 100644 --- a/tensorboard/components/tf_categorization_utils/test/categorizationUtilsTests.ts +++ b/tensorboard/components/tf_categorization_utils/test/categorizationUtilsTests.ts @@ -194,261 +194,6 @@ describe('categorizationUtils', () => { assert.deepEqual(actual, expected); }); }); - - describe('categorizeSelection', () => { - const {categorizeSelection} = tf_categorization_utils; - - beforeEach(function() { - const tag1 = { - id: 1, pluginName: 'scalar', - name: 'tag1', displayName: 'tag1', - }; - const tag2_1 = { - id: 2, pluginName: 'scalar', - name: 'tag2/subtag1', displayName: 'tag2/subtag1', - }; - const tag2_2 = { - id: 3, pluginName: 'scalar', - name: 'tag2/subtag2', displayName: 'tag2/subtag2', - }; - const tag3 = { - id: 4, pluginName: 'scalar', - name: 'tag3', displayName: 'tag3', - }; - const tag4 = { - id: 5, pluginName: 'custom_scalar', - name: 'tag4', displayName: 'tag4', - }; - - this.run1 = {id: 1, name: 'run1', startTime: 10, tags: [tag1, tag4]}; - this.run2 = {id: 2, name: 'run2', startTime: 5, tags: [tag2_1, tag2_2]}; - this.run3 = {id: 3, name: 'run3', startTime: 0, tags: [tag2_1, tag3]}; - - this.selection1 = { - experiment: {id: 1, name: 'exp1', startTime: 0}, - runs: [this.run1, this.run2], - tagRegex: '', - }; - this.selection2 = { - experiment: {id: 2, name: 'exp2', startTime: 0}, - runs: [this.run2, this.run3], - tagRegex: '(subtag1|tag3)', - }; - this.selection3 = { - experiment: {id: 3, name: 'exp3', startTime: 0}, - runs: [this.run1, this.run2, this.run3], - tagRegex: 'junk', - }; - }); - - it('merges the results of the query and the prefix groups', function() { - const result = categorizeSelection( - [this.selection1], 'scalar'); - - expect(result).to.have.lengthOf(3); - expect(result[0]).to.have.property('metadata') - .that.has.property('type', CategoryType.SEARCH_RESULTS); - - expect(result[1]).to.have.property('metadata') - .that.has.property('type', CategoryType.PREFIX_GROUP); - expect(result[2]).to.have.property('metadata') - .that.has.property('type', CategoryType.PREFIX_GROUP); - }); - - describe('search group', () => { - it('filters groups by tag with a tagRegex', function() { - const [searchResult] = categorizeSelection( - [this.selection2], 'scalar'); - - // should match 'tag2/subtag1' and 'tag3'. - expect(searchResult).to.have.property('items') - .that.has.lengthOf(2); - expect(searchResult.items[0]).to.have.property('tag', 'tag2/subtag1'); - expect(searchResult.items[0]).to.have.property('series') - .that.deep.equal([ - { - experiment: this.selection2.experiment, - run: 'run2', - tag: 'tag2/subtag1', - }, - { - experiment: this.selection2.experiment, - run: 'run3', - tag: 'tag2/subtag1', - }, - ]); - expect(searchResult.items[1]).to.have.property('tag', 'tag3'); - expect(searchResult.items[1]).to.have.property('series') - .that.deep.equal([ - { - experiment: this.selection2.experiment, - run: 'run3', - tag: 'tag3' - }, - ]); - }); - - it('combines selection without tagRegex with one', function() { - const sel1 = this.selection1; - const sel2 = this.selection2; - const [searchResult] = categorizeSelection([sel1, sel2], 'scalar'); - - // should match 'tag1', 'tag2/subtag1', 'tag2/subtag2', and 'tag3'. - expect(searchResult).to.have.property('items') - .that.has.lengthOf(4); - expect(searchResult.items[0]).to.have.property('tag', 'tag1'); - expect(searchResult.items[1]).to.have.property('tag', 'tag2/subtag1'); - expect(searchResult.items[2]).to.have.property('tag', 'tag2/subtag2'); - expect(searchResult.items[3]).to.have.property('tag', 'tag3'); - - expect(searchResult.items[1]).to.have.property('series') - .that.has.lengthOf(3) - .and.that.deep.equal([ - {experiment: sel1.experiment, run: 'run2', tag: 'tag2/subtag1'}, - {experiment: sel2.experiment, run: 'run2', tag: 'tag2/subtag1'}, - {experiment: sel2.experiment, run: 'run3', tag: 'tag2/subtag1'}, - ]); - }); - - it('keeps name as empty if all selections have no regex', function() { - const sel1 = this.selection1; - const sel2 = Object.assign({}, this.selection2, {tagRegex: ''}); - const [searchResult] = categorizeSelection([sel1, sel2], 'scalar'); - - expect(searchResult).to.have.property('items') - .that.has.lengthOf(4); - expect(searchResult).to.have.property('name', ''); - }); - - it('reports bad regex when at least one selection is bad', function() { - const sel1 = this.selection1; - const sel2 = Object.assign({}, this.selection2, {tagRegex: '))'}); - const [searchResult] = categorizeSelection([sel1, sel2], 'scalar'); - - expect(searchResult).to.have.property('metadata') - .that.has.property('validRegex', false); - }); - - it('sorts the tag by name', function() { - const [searchResult] = categorizeSelection( - [this.selection2, this.selection1], 'scalar'); - - // should match 'tag1', 'tag2/subtag1', 'tag2/subtag2', and 'tag3'. - expect(searchResult).to.have.property('items') - .that.has.lengthOf(4); - expect(searchResult.items[0]).to.have.property('tag', 'tag1'); - expect(searchResult.items[1]).to.have.property('tag', 'tag2/subtag1'); - expect(searchResult.items[2]).to.have.property('tag', 'tag2/subtag2'); - expect(searchResult.items[3]).to.have.property('tag', 'tag3'); - }); - - it('returns name `multi` when there are multiple selections', function() { - const [searchResult2] = categorizeSelection( - [this.selection2], 'scalar'); - expect(searchResult2).to.have.property('name', '(subtag1|tag3)'); - - const [searchResult1] = categorizeSelection( - [this.selection1, this.selection2], 'scalar'); - expect(searchResult1).to.have.property('name', 'multi'); - }); - - it('returns an empty array when tagRegex does not match any', function() { - const result = categorizeSelection([this.selection3], 'custom_scalar'); - - expect(result).to.have.lengthOf(2); - expect(result[0]).to.have.property('items') - .that.has.lengthOf(0); - }); - - it('omits selection from tag series when its regex does not match', - function() { - const [searchResult] = categorizeSelection( - [this.selection1, this.selection3], 'scalar'); - - // should match 'tag1', 'tag2/subtag1', 'tag2/subtag2', and 'tag3'. - expect(searchResult).to.have.property('items') - .that.has.lengthOf(3); - expect(searchResult.items[0]).to.have.property('tag', 'tag1'); - expect(searchResult.items[1]).to.have.property('tag', 'tag2/subtag1'); - expect(searchResult.items[2]).to.have.property('tag', 'tag2/subtag2'); - - // experiment3 also matches the tag1 but it has tagRegex of `junk`. - expect(searchResult.items[0]).to.have.property('series') - .that.deep.equal([ - { - experiment: this.selection1.experiment, - run: 'run1', - tag: 'tag1', - }, - ]); - }); - }); - - describe('prefix group', () => { - it('creates a group when a tag misses separator', function() { - const result = categorizeSelection([this.selection1], 'scalar'); - - expect(result[1]).to.have.property('items') - .that.has.lengthOf(1); - - expect(result[1]).to.have.property('name', 'tag1'); - expect(result[1].items[0]).to.have.property('tag', 'tag1'); - expect(result[1].items[0]).to.have.property('series') - .that.has.lengthOf(1); - }); - - it('creates a grouping when tag has a separator', function() { - const result = categorizeSelection([this.selection1], 'scalar'); - - expect(result[2]).to.have.property('items') - .that.has.lengthOf(2); - - expect(result[2]).to.have.property('name', 'tag2'); - expect(result[2].items[0]).to.have.property('tag', 'tag2/subtag1'); - expect(result[2].items[1]).to.have.property('tag', 'tag2/subtag2'); - expect(result[2].items[0]).to.have.property('series') - .that.has.lengthOf(1); - }); - - it('creates a group with items with experiment and run', function() { - const sel = this.selection1; - const result = categorizeSelection([sel], 'scalar'); - - expect(result[1].items[0]).to.have.property('series') - .that.has.lengthOf(1) - .and.that.deep.equal([ - {experiment: sel.experiment, run: 'run1', tag: 'tag1'}, - ]); - }); - - it('creates distinct subitems when tags exactly match', function() { - const sel = this.selection2; - const result = categorizeSelection([sel], 'scalar'); - expect(result[1].items[0]).to.have.property('series') - .that.has.lengthOf(2) - .and.that.deep.equal([ - {experiment: sel.experiment, run: 'run2', tag: 'tag2/subtag1'}, - {experiment: sel.experiment, run: 'run3', tag: 'tag2/subtag1'}, - ]); - }); - - it('filters out tags of a different plugin', function() { - const sel = this.selection3; - const result = categorizeSelection([sel], 'custom_scalar'); - - expect(result).to.have.lengthOf(2); - expect(result[1]).to.have.property('name', 'tag4'); - expect(result[1]).to.have.property('items') - .that.has.lengthOf(1); - expect(result[1].items[0]).to.have.property('series') - .that.has.lengthOf(1) - .and.that.deep.equal([ - {experiment: sel.experiment, run: 'run1', tag: 'tag4'}, - ]); - }); - }); - }); - }); } // namespace tf_categorization_utils diff --git a/tensorboard/components/tf_data_selector/BUILD b/tensorboard/components/tf_data_selector/BUILD deleted file mode 100644 index 9455c6d476..0000000000 --- a/tensorboard/components/tf_data_selector/BUILD +++ /dev/null @@ -1,55 +0,0 @@ -package(default_visibility = ["//tensorboard:internal"]) - -load("//tensorboard/defs:web.bzl", "tf_web_library") - -licenses(["notice"]) # Apache 2.0 - -tf_web_library( - name = "tf_data_selector", - srcs = [ - "experiment-selector.html", - "experiment-selector.ts", - "storage-utils.html", - "storage-utils.ts", - "tf-collapsible-data-selector.html", - "tf-collapsible-data-selector.ts", - "tf-data-select-row.html", - "tf-data-select-row.ts", - "tf-data-selector-advanced.html", - "tf-data-selector-advanced.ts", - "tf-data-selector-simple.html", - "tf-data-selector-simple.ts", - ], - path = "/tf-data-selector", - visibility = ["//visibility:public"], - deps = [ - ":type", - "@org_polymer_iron_collapse", - "@org_polymer_iron_icon", - "@org_polymer_paper_button", - "@org_polymer_paper_checkbox", - "@org_polymer_paper_icon_button", - "@org_polymer_paper_input", - "@org_polymer_paper_styles", - "@org_polymer_paper_tooltip", - "//tensorboard/components/tf_backend", - "//tensorboard/components/tf_color_scale", - "//tensorboard/components/tf_dashboard_common", - "//tensorboard/components/tf_imports:lodash", - "//tensorboard/components/tf_imports:polymer", - "//tensorboard/components/tf_storage", - ], -) - -tf_web_library( - name = "type", - srcs = [ - "type.html", - "type.ts", - ], - path = "/tf-data-selector", - visibility = ["//visibility:public"], - deps = [ - "//tensorboard/components/tf_backend:type", - ], -) diff --git a/tensorboard/components/tf_data_selector/experiment-selector.html b/tensorboard/components/tf_data_selector/experiment-selector.html deleted file mode 100644 index 9c4f5e3f75..0000000000 --- a/tensorboard/components/tf_data_selector/experiment-selector.html +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - diff --git a/tensorboard/components/tf_data_selector/experiment-selector.ts b/tensorboard/components/tf_data_selector/experiment-selector.ts deleted file mode 100644 index 14631a7a9f..0000000000 --- a/tensorboard/components/tf_data_selector/experiment-selector.ts +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the 'License'); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an 'AS IS' BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ -namespace tf_data_selector { - -Polymer({ - is: 'experiment-selector', - properties: { - excludeExperiments: { - type: Array, - value: (): Array => [], - }, - - alwaysExpanded: { - type: Boolean, - value: false, - }, - - _expanded: { - type: Boolean, - value: false, - }, - - _allExperiments: { - type: Array, - value: (): Array => [], - }, - - _experimentColoring: { - type: Object, - value: { - getColor: (item) => tf_color_scale.experimentsColorScale(item.title), - }, - }, - - _selectedExpOptions: { - type: Array, - value: (): Array => [], - }, - }, - - observers: [ - '_changeExpanded(alwaysExpanded)', - ], - - attached() { - this._updateExpKey = tf_backend.experimentsStore - .addListener(() => this._updateExps()); - this._updateExps(); - }, - - detached() { - tf_backend.experimentsStore.removeListenerByKey(this._updateExpKey); - }, - - _updateExps() { - this.set('_allExperiments', tf_backend.experimentsStore.getExperiments()); - }, - - _getExperimentOptions(_) { - const exclude = new Set(this.excludeExperiments.map(({id}) => id)); - return this._allExperiments - .filter(({id}) => !exclude.has(id)) - .map(exp => ({ - id: exp.id, - title: exp.name, - subtitle: exp.startedTime, - })); - }, - - _changeExpanded() { - if (this.alwaysExpanded && !this._expanded) { - this._expanded = true; - } - }, - - _toggle() { - this._expanded = !this._expanded; - }, - - _addExperiments() { - const lookupMap = new Map(this._allExperiments.map(e => [e.id, e])); - const newItems = this._selectedExpOptions - .map(({id}) => lookupMap.get(id)); - this._expanded = false; - this.fire('experiment-added', newItems); - }, - - _getAddLabel(_) { - switch (this._selectedExpOptions.length) { - case 0: - case 1: - return 'Add'; - default: - return 'Add All' - } - }, - -}); - -} // namespace tf_data_selector diff --git a/tensorboard/components/tf_data_selector/storage-utils.html b/tensorboard/components/tf_data_selector/storage-utils.html deleted file mode 100644 index fc897522fe..0000000000 --- a/tensorboard/components/tf_data_selector/storage-utils.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - diff --git a/tensorboard/components/tf_data_selector/storage-utils.ts b/tensorboard/components/tf_data_selector/storage-utils.ts deleted file mode 100644 index 7c41f34a7b..0000000000 --- a/tensorboard/components/tf_data_selector/storage-utils.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the 'License'); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an 'AS IS' BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ -namespace tf_data_selector { - -export function decodeIdArray(str: string): Array { - return str.split(',') - .map(idStr => parseInt(idStr, 10)) - .filter(n => !isNaN(n)); -} - -export function encodeIdArray(arr: Array): string { - return arr.map(encodeId).join(','); -} - -export function encodeId(id: number): string { - return String(id); -} - -export const NO_EXPERIMENT_ID = null; - -export const STORAGE_ALL_VALUE = '$all'; -export const STORAGE_NONE_VALUE = '$none'; - -export const { - getInitializer: getIdInitializer, - getObserver: getIdObserver, - set: setId, -} = tf_storage.makeBindings( - (str: string): number[] => tf_data_selector.decodeIdArray(str), - (ids: number[]): string => tf_data_selector.encodeIdArray(ids)); - -} // namespace tf_data_selector diff --git a/tensorboard/components/tf_data_selector/test/BUILD b/tensorboard/components/tf_data_selector/test/BUILD deleted file mode 100644 index 83436ccc61..0000000000 --- a/tensorboard/components/tf_data_selector/test/BUILD +++ /dev/null @@ -1,29 +0,0 @@ -package( - default_testonly = True, - default_visibility = ["//tensorboard:internal"], -) - -load("//tensorboard/defs:web.bzl", "tf_web_library", "tf_web_test") - -licenses(["notice"]) # Apache 2.0 - -tf_web_test( - name = "test", - web_library = ":test_web_library", - src = "/tf-data-selector/test/tests.html", -) - -tf_web_library( - name = "test_web_library", - srcs = [ - "tests.html", - "storage-utils-test.ts", - ], - path = "/tf-data-selector/test", - deps = [ - "//tensorboard/components/tf_data_selector", - "//tensorboard/components/tf_imports:polymer", - "//tensorboard/components/tf_imports:web_component_tester", - "//tensorboard/components/tf_imports:webcomponentsjs", - ], -) diff --git a/tensorboard/components/tf_data_selector/test/storage-utils-test.ts b/tensorboard/components/tf_data_selector/test/storage-utils-test.ts deleted file mode 100644 index d7c8155e9c..0000000000 --- a/tensorboard/components/tf_data_selector/test/storage-utils-test.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the 'License'); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an 'AS IS' BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ -namespace tf_data_selector { - -const {assert} = chai; - -describe('storageUtils', () => { - describe('decodeIdArray', () => { - it('decodes list of ids from a string', () => { - const actual = tf_data_selector.decodeIdArray('1,2,3,100'); - assert.deepEqual(actual, [1, 2, 3, 100]); - }); - - it('ignores stringified float', () => { - const actual = tf_data_selector.decodeIdArray('1.weeeeeeeee'); - assert.deepEqual(actual, [1]); - }); - - it('filters non-number (including inf) from decoded ids', () => { - const actual = tf_data_selector.decodeIdArray(',1, 2,0,!a,Infinity'); - assert.deepEqual(actual, [1, 2, 0]); - }); - }); - - describe('encodeIdArray', () => { - it('encodes list of ids', () => { - const actual = tf_data_selector.encodeIdArray([1, 2, 3, 100]); - assert.deepEqual(actual, '1,2,3,100'); - }); - - it('behaves ok for floats', () => { - const actual = tf_data_selector.encodeIdArray([1, 1.9]); - assert.equal(actual, '1,1.9'); - }); - - it('behaves ok with large numbers', () => { - const actual = tf_data_selector.encodeIdArray([-Infinity, Infinity]); - assert.equal(actual, '-Infinity,Infinity'); - }); - }); -}); - -} // namespace tf_data_selector diff --git a/tensorboard/components/tf_data_selector/test/tests.html b/tensorboard/components/tf_data_selector/test/tests.html deleted file mode 100644 index c7ae145397..0000000000 --- a/tensorboard/components/tf_data_selector/test/tests.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - diff --git a/tensorboard/components/tf_data_selector/tf-collapsible-data-selector.html b/tensorboard/components/tf_data_selector/tf-collapsible-data-selector.html deleted file mode 100644 index fc79bcda79..0000000000 --- a/tensorboard/components/tf_data_selector/tf-collapsible-data-selector.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/tensorboard/components/tf_data_selector/tf-collapsible-data-selector.ts b/tensorboard/components/tf_data_selector/tf-collapsible-data-selector.ts deleted file mode 100644 index 21329d1eb5..0000000000 --- a/tensorboard/components/tf_data_selector/tf-collapsible-data-selector.ts +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the 'License'); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an 'AS IS' BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ -namespace tf_data_selector { - -enum Mode { - SIMPLE, - ADVANCED, -} - -Polymer({ - is: 'tf-collapsible-data-selector', - properties: { - _simpleSelection: { - type: Object, - value: () => ({}), - }, - - _advancedSelection: { - type: Object, - value: () => ({}), - }, - - selection: { - type: Object, - computed: '_computeSelection(_simpleSelection, _advancedSelection, _mode)', - notify: true, - }, - - activePlugins: Array, - - opened: { - type: Boolean, - reflectToAttribute: true, - value: true, - }, - - _mode: { - type: Number, - value: Mode.SIMPLE, - }, - }, - - _computeSelection() { - if (this._mode == Mode.SIMPLE) return this._simpleSelection; - return this._advancedSelection; - }, - - _toggleOpened() { - this.opened = !this.opened; - }, - - _getExperimentStyle(experiment) { - if (!experiment) return ''; - - const color = tf_color_scale.experimentsColorScale(experiment.name); - return `background-color: ${color};`; - }, - - _isSimpleMode(mode) { - return mode == Mode.SIMPLE; - }, - - _toggleMode() { - const curMode = this._mode; - const nextMode = curMode == Mode.SIMPLE ? Mode.ADVANCED : Mode.SIMPLE; - this._mode = nextMode; - }, - -}); - -} // namespace tf_data_selector diff --git a/tensorboard/components/tf_data_selector/tf-data-select-row.html b/tensorboard/components/tf_data_selector/tf-data-select-row.html deleted file mode 100644 index 44915a0b0b..0000000000 --- a/tensorboard/components/tf_data_selector/tf-data-select-row.html +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/tensorboard/components/tf_data_selector/tf-data-select-row.ts b/tensorboard/components/tf_data_selector/tf-data-select-row.ts deleted file mode 100644 index 47acbdaad4..0000000000 --- a/tensorboard/components/tf_data_selector/tf-data-select-row.ts +++ /dev/null @@ -1,303 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the 'License'); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an 'AS IS' BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ -namespace tf_data_selector { - -enum Type { - RUN = 1, - TAG, -} - -const MAX_RUNS_TO_ENABLE_BY_DEFAULT = 20; - -Polymer({ - is: 'tf-data-select-row', - properties: { - experiment: { - type: Object, - value: () => ({ - id: null, - name: 'Unknown experiment', - startTime: null, - }), - }, - - enabled: { - type: Boolean, - notify: true, - value: true, - }, - - checkboxColor: { - type: String, - value: '', - }, - - // Required field. - persistenceId: String, - - noExperiment: { - type: Boolean, - value: false, - }, - - shouldColorRuns: { - type: Boolean, - value: false, - }, - - _coloring: { - type: Object, - computed: '_getColoring(shouldColorRuns)', - }, - - _runs: { - type: Array, - value: (): Array => [], - }, - - _runSelectionStateString: {type: String, value: ''}, - - // ListItem requires `id` and it is synthesized from name when it is in the - // `noExperiment` mode. - _selectedRuns: { - type: Array, - value: (): Array => [], - }, - - _tagRegex: { - type: String, - value: '', - observer: '_persistRegex', - }, - - _storageBinding: { - type: Object, - value: () => null, - }, - }, - - listeners: { - 'dom-change': '_synchronizeColors', - }, - - observers: [ - '_immutablePropInvarianceViolated(persistenceId.*)', - '_immutablePropInvarianceViolated(experiment.*)', - '_synchronizeColors(checkboxColor)', - '_persistSelectedRuns(_selectedRuns)', - '_fireChange(_selectedRuns, _tagRegex)', - ], - - _getPersistenceKey(type: Type): string { - const id = this.persistenceId; - switch (type) { - case Type.RUN: - // Prefix with 'g' to denote a group. - return `gr${id}`; - case Type.TAG: - return `gt${id}`; - } - }, - - attached(): void { - if (this.persistenceId == null) { - throw new RangeError('Required `persistenceId` missing'); - } - - this._initFromStorage(); - this._initRunsAndTags() - .then(() => { - if (this._runSelectionStateString) return; - const val = this._runs.length <= MAX_RUNS_TO_ENABLE_BY_DEFAULT ? - STORAGE_ALL_VALUE : STORAGE_NONE_VALUE; - this._storageBinding.set(this._getPersistenceKey(Type.RUN), val, - {defaultValue: ''}); - this._runSelectionStateString = val; - }); - }, - - detached(): void { - this._isDataReady = false; - if (this._storageBinding) this._storageBinding.disposeBinding(); - }, - - _initFromStorage() { - if (this._storageBinding) this._storageBinding.disposeBinding(); - this._storageBinding = tf_storage.makeBindings(x => x, x => x); - const runInitializer = this._storageBinding.getInitializer( - this._getPersistenceKey(Type.RUN), - { - defaultValue: '', - polymerProperty: '_runSelectionStateString', - }); - runInitializer.call(this); - const tagInitializer = this._storageBinding.getInitializer( - this._getPersistenceKey(Type.TAG), - {defaultValue: '', polymerProperty: '_tagRegex'}); - tagInitializer.call(this); - }, - - _initRunsAndTags(): Promise { - this._isDataReady = false; - return this._fetchRunsAndTags() - .then(() => { - this._isDataReady = true; - }); - }, - - _immutablePropInvarianceViolated(change) { - // We allow property to change many times before the component is attached - // to DOM. - if (this.isAttached) { - throw new Error(`Invariance Violation: ` + - `Expected property '${change.path}' not to change.`); - } - }, - - _synchronizeColors() { - const cb = this.$$('#checkbox'); - if (!cb) return; - - const color = this.checkboxColor; - cb.customStyle['--paper-checkbox-checked-color'] = color; - cb.customStyle['--paper-checkbox-checked-ink-color'] = color; - cb.customStyle['--paper-checkbox-unchecked-color'] = color; - cb.customStyle['--paper-checkbox-unchecked-ink-color'] = color; - - window.requestAnimationFrame(() => this.updateStyles()); - }, - - _fetchRunsAndTags(): Promise { - const requestManager = new tf_backend.RequestManager(); - if (this.noExperiment) { - const fetchRuns = requestManager.request(tf_backend.getRouter().runs()); - return Promise.all([fetchRuns]).then(([runs]) => { - this.set('_runs', Array.from(new Set(runs)).map(runName => ({ - id: null, - name: runName, - startedTime: null, - }))); - }); - } - - console.assert(this.experiment.id != null, 'Expected an experiment Id'); - - const url = tf_backend.getRouter().runsForExperiment(this.experiment.id); - return requestManager.request(url).then(runs => { - this.set('_runs', runs); - }); - }, - - _getRunOptions(_): Array { - return this._runs.map(run => ({ - // /data/runs endpoint does not return ids. In case of logdir data source, - // runs cannot have an id and, for filtered-checkbox-list, we need to - // synthesize id from the name. - id: this._getSyntheticRunId(run), - title: run.name, - })); - }, - - _persistSelectedRuns(): void { - if (!this._isDataReady) return; - const value = this._serializeValue( - this._runs, - this._selectedRuns.map(({id}) => id)); - this._storageBinding.set(this._getPersistenceKey(Type.RUN), value, - {defaultValue: ''}); - }, - - _getRunsSelectionState(): Object { - const allIds = this._runs.map(r => this._getSyntheticRunId(r)); - const ids = this._deserializeValue(allIds, this._runSelectionStateString); - const prevSelection = new Set(ids); - const newSelection = {}; - allIds.forEach(id => newSelection[id] = prevSelection.has(id)); - return newSelection; - }, - - _persistRegex(): void { - if (!this._isDataReady) return; - const value = this._tagRegex; - this._storageBinding.set(this._getPersistenceKey(Type.TAG), value, - {defaultValue: ''}); - }, - - _fireChange(_, __): void { - const runMap = new Map( - this._runs.map(run => [this._getSyntheticRunId(run), run])); - this.fire('selection-changed', { - runs: this._selectedRuns.map(({id}) => runMap.get(id)) - .filter(Boolean) - .map(run => ({ - id: run.id, - name: run.name, - startTime: run.startTime, - tags: run.tags, - })), - tagRegex: this._tagRegex, - }); - }, - - _removeRow(): void { - // Clear persistence when being removed. - this._storageBinding.set( - this._getPersistenceKey(Type.RUN), '', {defaultValue: ''}); - this._storageBinding.set( - this._getPersistenceKey(Type.TAG), '', {defaultValue: ''}); - this.fire('remove'); - }, - - _serializeValue( - source: Array, selectedIds: Array) { - if (selectedIds.length == source.length) return STORAGE_ALL_VALUE; - if (selectedIds.length == 0) return STORAGE_NONE_VALUE; - - return this.noExperiment ? - JSON.stringify(selectedIds) : - tf_data_selector.encodeIdArray((selectedIds as Array)); - }, - - _deserializeValue(allValues: Array, str: string) { - if (str == STORAGE_ALL_VALUE) return allValues; - if (str == STORAGE_NONE_VALUE) return []; - if (!this.noExperiment) return tf_data_selector.decodeIdArray(str); - let parsed = []; - try { - parsed = JSON.parse(str); - } catch (e) { - /* noop */ - } - return Array.isArray(parsed) ? parsed : []; - }, - - _getColoring() { - return { - getColor: this.shouldColorRuns ? - (item) => tf_color_scale.runsColorScale(item.title) : - () => '', - }; - }, - - _getSyntheticRunId(run) { - return this.noExperiment ? run.name : run.id; - }, - - _fireCheckboxToggled() { - this.fire('checkbox-toggle'); - }, -}); - -} // namespace tf_data_selector diff --git a/tensorboard/components/tf_data_selector/tf-data-selector-advanced.html b/tensorboard/components/tf_data_selector/tf-data-selector-advanced.html deleted file mode 100644 index 48de6ab639..0000000000 --- a/tensorboard/components/tf_data_selector/tf-data-selector-advanced.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/tensorboard/components/tf_data_selector/tf-data-selector-advanced.ts b/tensorboard/components/tf_data_selector/tf-data-selector-advanced.ts deleted file mode 100644 index 252bd718c0..0000000000 --- a/tensorboard/components/tf_data_selector/tf-data-selector-advanced.ts +++ /dev/null @@ -1,294 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the 'License'); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an 'AS IS' BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ -namespace tf_data_selector { - -Polymer({ - is: 'tf-data-selector-advanced', - properties: { - _allExperimentsFetched: { - type: Boolean, - value: false, - }, - - _allExperiments: { - type: Array, - value: (): Array => [], - }, - - // Subset of allExperiments user chose and added. - _experimentIds: { - type: Array, - value: getIdInitializer('e', { - defaultValue: [], - polymerProperty: '_experimentIds', - }), - }, - - _experiments: { - type: Array, - value: (): Array => [], - }, - - _enabledExperimentIds: { - type: Array, - value: getIdInitializer('ee', { - defaultValue: [], - polymerProperty: '_enabledExperimentIds', - }), - }, - - _selections: { - type: Object, - value: (): Map => { - return new Map(); - }, - }, - - activePlugins: { - type: Array, - value: (): string[] => [], - }, - - // Output property. It has subset of _selections. - selection: { - type: Object, - notify: true, - computed: '_computeSelection(_enabledExperimentIds.*, _selections.*, activePlugins.*)', - }, - - _canCompareExperiments: { - type: Boolean, - value: false - }, - - _shouldColorRuns: { - type: Boolean, - computed: '_computeShouldColorRuns(_experiments.*)', - }, - - }, - - behaviors: [ - tf_dashboard_common.ArrayUpdateHelper, - ], - - observers: [ - '_updateExperiments(_allExperiments, _experimentIds)', - '_pruneSelections(_experimentIds.*)', - '_pruneExperimentIds(_allExperiments.*)', - '_pruneEnabledExperiments(_experimentIds.*)', - '_persistExperimentIds(_experimentIds.*)', - '_persistEnabledExperiments(_enabledExperimentIds.*)', - ], - - _persistExperimentIds: getIdObserver('e', { - defaultValue: [], - polymerProperty: '_experimentIds', - }), - - _persistEnabledExperiments: getIdObserver('ee', { - defaultValue: [], - polymerProperty: '_enabledExperimentIds', - }), - - attached() { - this._updateExpKey = tf_backend.experimentsStore.addListener(() => { - this._allExperiments = tf_backend.experimentsStore.getExperiments(); - this._allExperimentsFetched = true; - }); - this._allExperiments = tf_backend.experimentsStore.getExperiments(); - this._allExperimentsFetched = tf_backend.experimentsStore.initialized; - - this._updateEnvKey = tf_backend.environmentStore.addListener(() => { - this._canCompareExperiments = tf_backend.Mode.DB == - tf_backend.environmentStore.getMode(); - }); - this._canCompareExperiments = tf_backend.Mode.DB == - tf_backend.environmentStore.getMode(); - }, - - detached() { - tf_backend.experimentsStore.removeListenerByKey(this._updateExpKey); - tf_backend.environmentStore.removeListenerByKey(this._updateEnvKey); - }, - - _getPersistenceId(experiment) { - return tf_data_selector.encodeId(experiment.id); - }, - - _isExperimentEnabled(experiment) { - const enabledExperimentIds = new Set(this._enabledExperimentIds); - return enabledExperimentIds.has(experiment.id); - }, - - _getExperimentColor(experiment: tf_backend.Experiment): string { - return tf_color_scale.experimentsColorScale(experiment.name); - }, - - _computeShouldColorRuns() { - return this._experiments.length <= 1; - }, - - /** - * Prunes away an experiment that has been removed from `_experiments` from - * the selection. - */ - _pruneSelections() { - if (!this._selections) return; - const experimentIds = new Set(this._experimentIds); - const newSelections = new Map(this._selections); - newSelections.forEach((_, id) => { - // No experiment selection is still a valid selection. Do not prune. - if (id == NO_EXPERIMENT_ID) return; - if (!experimentIds.has(id)) newSelections.delete(id); - }); - this._selections = newSelections; - }, - - _pruneExperimentIds() { - if (!this._allExperimentsFetched) return; - const allExpIds = new Set(this._allExperiments.map(({id}) => id)); - this._experimentIds = this._experimentIds.filter(id => allExpIds.has(id)); - }, - - _pruneEnabledExperiments() { - // When the component never fully loaded the list of experiments, it - // cannot correctly prune/adjust the enabledExperiments. - if (!this._allExperimentsFetched) return; - const expIds = new Set(this._experimentIds); - this._enabledExperimentIds = this._enabledExperimentIds - .filter(id => expIds.has(id)); - }, - - _computeSelection() { - if (this._canCompareExperiments) { - const activePluginNames = new Set(this.activePlugins); - const selections = this._enabledExperimentIds - .filter(id => this._selections.has(id)) - .map(id => this._selections.get(id) as Selection) - .map(selection => { - const updatedSelection = Object.assign({}, selection); - updatedSelection.runs = selection.runs.map(run => { - return Object.assign({}, run, { - tags: run.tags - .filter(tag => activePluginNames.has(tag.pluginName)), - }); - }).filter(run => run.tags.length); - return updatedSelection; - }); - - // Single selection: one experimentful selection whether it is enabled or - // not. - // NOTE: `_selections` can contain not only selections for experiment - // diffing but also one for no-experiment mode. If it contains one, - // "remove" the size by one. - const isSingleSelection = this._selections.size == - 1 + Number(this._selections.has(NO_EXPERIMENT_ID)); - return { - type: isSingleSelection ? - tf_data_selector.Type.SINGLE : tf_data_selector.Type.COMPARISON, - selections, - }; - } - return { - type: tf_data_selector.Type.WITHOUT_EXPERIMENT, - selections: [this._selections.get(NO_EXPERIMENT_ID)], - }; - }, - - _selectionChanged(event) { - event.stopPropagation(); - if (!this.isAttached || !event.target.isAttached) return; - const {runs, tagRegex} = event.detail; - const experiment = event.target.experiment; - const expId = experiment.id != null ? experiment.id : NO_EXPERIMENT_ID; - - // Check if selction change event was triggered from a removed row. Removal - // triggers change in persistence (clears the value) and this causes - // property to change which in turn triggers an event. If there is any - // asynchronity in propagating the change from the row, below condition is - // truthy. - if (expId != NO_EXPERIMENT_ID && !this._experimentIds.includes(expId)) { - return; - } - - const newSelections = new Map(this._selections); - newSelections.set(expId, {experiment, runs, tagRegex}); - - // Ignore the selection changed event if it makes no tangible difference to - // the _selections. - if (_.isEqual(newSelections, this._selections)) return; - - this._selections = newSelections; - }, - - _updateExperiments() { - const lookup = new Map(this._allExperiments.map(e => [e.id, e])); - const experiments = this._experimentIds - .filter(id => lookup.has(id)) - .map(id => lookup.get(id)); - - this.updateArrayProp('_experiments', experiments, exp => exp.id); - }, - - _addExperiments(event) { - const addedIds = event.detail.map(({id}) => id); - this._experimentIds = uniqueAdd(this._experimentIds, addedIds); - - // Enable newly added experiments by default - this._enabledExperimentIds = uniqueAdd( - this._enabledExperimentIds, - addedIds); - }, - - _removeExperiment(event) { - const removedId = event.target.experiment.id; - // Changing _experimentIds will remove the id from _enabledExperimentIds. - this._experimentIds = this._experimentIds.filter(id => id != removedId); - }, - - _experimentCheckboxToggled(e) { - const newId = e.target.experiment.id; - if (e.target.enabled) { - this._enabledExperimentIds = uniqueAdd( - this._enabledExperimentIds, - [newId]); - } else { - this._enabledExperimentIds = this._enabledExperimentIds - .filter(id => id != newId); - } - }, - - _getAddComparisonVisible() { - return this._canCompareExperiments && - this._allExperiments.length > this._experiments.length; - }, - - _getAddComparisonAlwaysExpanded() { - return this._canCompareExperiments && !this._experiments.length; - }, - -}); - -/** - * Append items to an array without duplicate entries. - */ -function uniqueAdd(to: T[], items: T[]): T[] { - const toSet = new Set(to); - items.forEach(item => toSet.add(item)); - return Array.from(toSet); -} - -} // namespace tf_data_selector diff --git a/tensorboard/components/tf_data_selector/tf-data-selector-simple.html b/tensorboard/components/tf_data_selector/tf-data-selector-simple.html deleted file mode 100644 index f134d94688..0000000000 --- a/tensorboard/components/tf_data_selector/tf-data-selector-simple.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/tensorboard/components/tf_data_selector/tf-data-selector-simple.ts b/tensorboard/components/tf_data_selector/tf-data-selector-simple.ts deleted file mode 100644 index 2a7bd42c86..0000000000 --- a/tensorboard/components/tf_data_selector/tf-data-selector-simple.ts +++ /dev/null @@ -1,228 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the 'License'); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an 'AS IS' BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ -namespace tf_data_selector { - -const NO_EXPERIMENT_ID = null; - -Polymer({ - is: 'tf-data-selector-simple', - properties: { - _allExperiments: { - type: Array, - value: (): tf_backend.Experiment[] => [], - }, - - _allRuns: { - type: Array, - value: (): string[] => [], - }, - - _selectedExperimentIds: { - type: Array, - value: getIdInitializer('e', { - defaultValue: [], - polymerProperty: '_selectedExperimentIds', - }), - }, - - _selectedExperiments: { - type: Array, - observer: '_persistExperimentIds', - }, - - _selectedRunNames: { - type: Array, - value: tf_storage.getObjectInitializer('runs', { - defaultValue: [], - polymerProperty: '_selectedRunNames', - }), - }, - - _selectedRuns: { - type: Array, - observer: '_persistRunNames', - }, - - _expToRunsAndTags: { - type: Object, - value: () => null, - }, - - _tagRegex: { - type: String, - value: tf_storage.getStringInitializer( - 'tagFilter', {defaultValue: '', polymerProperty: '_tagRegex'}), - observer: '_persistTagFilter', - }, - - _requestManager: { - type: Object, - value: () => new tf_backend.RequestManager(), - }, - - // Output property. It has subset of _selections. - selection: { - type: Object, - notify: true, - computed: '_computeSelection(_selectedExperiments, _expToRunsAndTags, _selectedRuns, _tagRegex)', - }, - }, - - observers: [ - '_fetchNewRunsAndTags(_selectedExperiments)', - ], - - _persistExperimentIds() { - const value = this._selectedExperiments.map(({id}) => id); - setId('e', value, {defaultValue: []}); - }, - - _persistRunNames() { - const value = this._selectedRuns.map(({id}) => id); - tf_storage.setObject('runs', value, {defaultValue: []}); - }, - - _persistTagFilter: tf_storage.getStringObserver( - 'tagFilter', {defaultValue: '', polymerProperty: '_tagRegex'}), - - attached() { - this._updateExpKey = tf_backend.experimentsStore.addListener(() => { - this._allExperiments = tf_backend.experimentsStore.getExperiments(); - }); - this._allExperiments = tf_backend.experimentsStore.getExperiments(); - - this._updateRunKey = tf_backend.runsStore.addListener(() => { - this._allRuns = Array.from(new Set(tf_backend.runsStore.getRuns())); - }); - this._allRuns = Array.from(new Set(tf_backend.runsStore.getRuns())); - }, - - detached() { - tf_backend.experimentsStore.removeListenerByKey(this._updateExpKey); - tf_backend.experimentsStore.removeListenerByKey(this._updateRunKey); - }, - - _getExperimentColor() { - return { - getColor: - (item: tf_dashboard_common.FilterableCheckboxListItem): string => - tf_color_scale.experimentsColorScale(item.title), - }; - }, - - _getRunColor() { - return { - getColor: - (item: tf_dashboard_common.FilterableCheckboxListItem): string => - tf_color_scale.runsColorScale(item.title), - }; - }, - - _getRunsUsesCheckboxColors(): boolean { - return this._selectedExperiments.length <= 1; - }, - - _getExperimentOptions(_): tf_dashboard_common.FilterableCheckboxListItem[] { - return this._allExperiments - .map(experiment => ({ - id: experiment.id, - title: experiment.name, - subtitle: getShortDateString(new Date(experiment.startTime)), - })); - }, - - _getRunOptions(): tf_dashboard_common.FilterableCheckboxListItem[] { - return this._allRuns.map(run => ({id: run, title: run})); - }, - - _getExperimentsSelectionState() { - const allIds = this._allExperiments.map(({id}) => id); - const selectedIds = new Set(this._selectedExperimentIds); - const state = {}; - allIds.forEach(id => state[id] = selectedIds.has(id)); - return state; - }, - - _getRunsSelectionState() { - const allIds = this._allRuns; - const selectedIds = new Set(this._selectedRunNames); - const state = {}; - allIds.forEach(id => state[id] = selectedIds.has(id)); - return state; - }, - - _computeSelection() { - const expMap = new Map(this._allExperiments.map(exp => [exp.id, exp])); - const selectedRunNames = new Set( - this._selectedRuns.map(({title}) => title)); - - const completeExps = this._selectedExperiments - .filter(({id}) => (this._expToRunsAndTags || new Map()).has(id)) - .map(({id}) => expMap.get(id)); - - const selections = completeExps.map(experiment => { - return { - experiment, - runs: this._expToRunsAndTags.get(experiment.id) - .filter(run => selectedRunNames.has(run.name)), - tagRegex: this._tagRegex, - }; - }); - - return { - type: selections.length == 1 ? - tf_data_selector.Type.SINGLE : tf_data_selector.Type.COMPARISON, - selections, - }; - }, - - _fetchNewRunsAndTags() { - const expMap = new Map(this._allExperiments.map(exp => [exp.id, exp])); - const expsToFetch = this._selectedExperiments - .filter(({id}) => !(this._expToRunsAndTags || new Map()).has(id)) - .map(({id}) => expMap.get(id)); - - const fetches = expsToFetch.map(exp => this._fetchRunsAndTags(exp)); - Promise.all(fetches).then(results => { - const newExpToRunsAndTags = new Map(this._expToRunsAndTags); - results.forEach((runs, index) => { - const exp = expsToFetch[index]; - newExpToRunsAndTags.set(exp.id, runs); - }); - this._expToRunsAndTags = newExpToRunsAndTags; - }); - }, - - _fetchRunsAndTags(exp: tf_backend.Experiment): Promise { - const id = exp.id; - console.assert(id != null, 'Expected an experiment Id'); - - const url = tf_backend.getRouter().runsForExperiment(id); - return this._requestManager.request(url); - }, - -}); - -function getShortDateString(date: Date): string { - return date.toLocaleDateString(undefined, { - month: 'long', - day: 'numeric', - hour: 'numeric', - minute: 'numeric', - second: 'numeric', - }); -} - -} // namespace tf_data_selector diff --git a/tensorboard/components/tf_data_selector/type.html b/tensorboard/components/tf_data_selector/type.html deleted file mode 100644 index 3a420261da..0000000000 --- a/tensorboard/components/tf_data_selector/type.html +++ /dev/null @@ -1,17 +0,0 @@ - - diff --git a/tensorboard/components/tf_data_selector/type.ts b/tensorboard/components/tf_data_selector/type.ts deleted file mode 100644 index 9c38ae002e..0000000000 --- a/tensorboard/components/tf_data_selector/type.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the 'License'); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an 'AS IS' BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ -namespace tf_data_selector { - -export enum Type { - WITHOUT_EXPERIMENT, - SINGLE, - COMPARISON, -} - -export type Selection = { - experiment?: tf_backend.Experiment, - runs: Array, - tagRegex: string, -} - -export type DataSelection = { - type: Type, - selections: Array -} - -} // namespace tf_data_selector diff --git a/tensorboard/components/tf_globals/globals.ts b/tensorboard/components/tf_globals/globals.ts index 3ba340e724..257ca4498b 100644 --- a/tensorboard/components/tf_globals/globals.ts +++ b/tensorboard/components/tf_globals/globals.ts @@ -37,8 +37,4 @@ export function getFakeHash() { return _fakeHash; } -export function getEnableDataSelector(): boolean { - return new URLSearchParams(window.location.search).has('EnableDataSelector'); -} - } // namespace tf_globals diff --git a/tensorboard/components/tf_tensorboard/BUILD b/tensorboard/components/tf_tensorboard/BUILD index 1bcebd8606..c1ee4e35f9 100644 --- a/tensorboard/components/tf_tensorboard/BUILD +++ b/tensorboard/components/tf_tensorboard/BUILD @@ -18,7 +18,6 @@ tf_web_library( ":registry", "//tensorboard/components/tf_backend", "//tensorboard/components/tf_dashboard_common", - "//tensorboard/components/tf_data_selector", "//tensorboard/components/tf_globals", "//tensorboard/components/tf_imports:lodash", "//tensorboard/components/tf_imports:polymer", diff --git a/tensorboard/components/tf_tensorboard/registry.ts b/tensorboard/components/tf_tensorboard/registry.ts index d1d4520e17..73f05a08c2 100644 --- a/tensorboard/components/tf_tensorboard/registry.ts +++ b/tensorboard/components/tf_tensorboard/registry.ts @@ -60,13 +60,6 @@ export interface Dashboard { * This allows the Polymer 'detached' event to happen. */ shouldRemoveDom: boolean; - - /** - * Whether to show a system data selector above the plugin. The data selector - * will allow user to select experiments, runs, and tags. The selection is - * injected as `dataSelection` property to the plugin. - */ - useDataSelector: boolean; } /** Typedef mapping plugin names to Dashboard registrations. */ diff --git a/tensorboard/components/tf_tensorboard/tf-tensorboard.html b/tensorboard/components/tf_tensorboard/tf-tensorboard.html index d2304312a3..c0e4ff82a2 100644 --- a/tensorboard/components/tf_tensorboard/tf-tensorboard.html +++ b/tensorboard/components/tf_tensorboard/tf-tensorboard.html @@ -26,7 +26,6 @@ - @@ -146,14 +145,6 @@

Settings

-