Skip to content

Commit 9e7ea16

Browse files
authored
Flatten table on sort (#4685)
1 parent bbd0d29 commit 9e7ea16

File tree

29 files changed

+2037
-915
lines changed

29 files changed

+2037
-915
lines changed

.codeclimate.json

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,29 @@
88
"demo/",
99
"extension/src/test/",
1010
"languageServer/src/test/",
11-
"webview/src/shared/components/icons/"
11+
"webview/src/shared/components/icons/",
12+
"webview/src/test/mockRowModel.ts"
1213
],
1314
"checks": {
1415
"file-lines": {
15-
"config": { "threshold": 300 }
16+
"config": {
17+
"threshold": 300
18+
}
19+
},
20+
"method-count": {
21+
"config": {
22+
"threshold": 30
23+
}
1624
},
17-
"method-count": { "config": { "threshold": 30 } },
1825
"method-lines": {
1926
"config": {
2027
"threshold": 40
2128
}
2229
},
2330
"method-complexity": {
24-
"config": { "threshold": 6 }
31+
"config": {
32+
"threshold": 6
33+
}
2534
}
2635
}
2736
}

extension/src/experiments/columns/collect/order.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { Column, ColumnType } from '../../webview/contract'
2-
import { EXPERIMENT_COLUMN_ID } from '../constants'
2+
import {
3+
EXPERIMENT_COLUMN_ID,
4+
BRANCH_COLUMN_ID,
5+
COMMIT_COLUMN_ID
6+
} from '../constants'
37

48
export const collectColumnOrder = async (
59
existingColumnOrder: string[],
@@ -25,6 +29,14 @@ export const collectColumnOrder = async (
2529
existingColumnOrder.unshift(EXPERIMENT_COLUMN_ID)
2630
}
2731

32+
if (!existingColumnOrder.includes(BRANCH_COLUMN_ID)) {
33+
existingColumnOrder.splice(1, 0, BRANCH_COLUMN_ID)
34+
}
35+
36+
if (!existingColumnOrder.includes(COMMIT_COLUMN_ID)) {
37+
existingColumnOrder.splice(2, 0, COMMIT_COLUMN_ID)
38+
}
39+
2840
return [
2941
...existingColumnOrder,
3042
...acc.timestamp,

extension/src/experiments/columns/constants.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,12 @@ export const timestampColumn: Column = {
1111
}
1212

1313
export const EXPERIMENT_COLUMN_ID = 'id'
14+
15+
export const COMMIT_COLUMN_ID = 'commit'
16+
export const BRANCH_COLUMN_ID = 'branch'
17+
18+
export const DEFAULT_COLUMN_IDS = [
19+
EXPERIMENT_COLUMN_ID,
20+
BRANCH_COLUMN_ID,
21+
COMMIT_COLUMN_ID
22+
]

extension/src/experiments/columns/model.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ import {
1212
limitSummaryOrder
1313
} from './util'
1414
import { collectColumnOrder } from './collect/order'
15+
import {
16+
BRANCH_COLUMN_ID,
17+
COMMIT_COLUMN_ID,
18+
DEFAULT_COLUMN_IDS
19+
} from './constants'
1520
import { Column, ColumnType } from '../webview/contract'
1621
import { ExpShowOutput } from '../../cli/dvc/contract'
1722
import { PersistenceKey } from '../../persistence/constants'
@@ -104,10 +109,10 @@ export class ColumnsModel extends PathSelectionModel<Column> {
104109

105110
public selectFirst(firstColumns: string[]) {
106111
const columnOrder = [
107-
'id',
112+
...DEFAULT_COLUMN_IDS,
108113
...firstColumns,
109114
...this.getColumnOrder().filter(
110-
column => !['id', ...firstColumns].includes(column)
115+
column => ![...DEFAULT_COLUMN_IDS, ...firstColumns].includes(column)
111116
)
112117
]
113118
this.setColumnOrder(columnOrder)
@@ -201,6 +206,13 @@ export class ColumnsModel extends PathSelectionModel<Column> {
201206
return this.setColumnOrderFromData(selectedColumns)
202207
}
203208
}
209+
210+
const maybeMissingDefaultColumns = [COMMIT_COLUMN_ID, BRANCH_COLUMN_ID]
211+
for (const id of maybeMissingDefaultColumns) {
212+
if (!this.columnOrderState.includes(id)) {
213+
return this.setColumnOrderFromData(selectedColumns)
214+
}
215+
}
204216
}
205217

206218
private transformAndSetChanges(data: ExpShowOutput) {

extension/src/experiments/model/index.ts

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -438,11 +438,19 @@ export class ExperimentsModel extends ModelWithPersistence {
438438
}
439439

440440
public getRowData() {
441-
const commitsBySha = this.applyFiltersToCommits()
441+
const workspaceRow = {
442+
branch: WORKSPACE_BRANCH,
443+
...this.addDetails(this.workspace)
444+
}
445+
const sorts = this.getSorts()
446+
const flattenRowData = sorts.length > 0
447+
if (flattenRowData) {
448+
return this.getFlattenedRowData(workspaceRow)
449+
}
450+
451+
const commitsBySha: { [sha: string]: Commit } = this.applyFiltersToCommits()
452+
const rows: Commit[] = [workspaceRow]
442453

443-
const rows: Commit[] = [
444-
{ branch: WORKSPACE_BRANCH, ...this.addDetails(this.workspace) }
445-
]
446454
for (const { branch, sha } of this.rowOrder) {
447455
const commit = commitsBySha[sha]
448456
if (!commit) {
@@ -829,4 +837,42 @@ export class ExperimentsModel extends ModelWithPersistence {
829837
}
830838
return commitsBySha
831839
}
840+
841+
private applyFiltersToFlattenedCommits() {
842+
const commitsBySha: { [sha: string]: Commit[] } = {}
843+
const filters = this.getFilters()
844+
845+
for (const commit of this.commits) {
846+
const commitWithSelectedAndStarred = this.addDetails(commit)
847+
const experiments = this.getExperimentsByCommit(
848+
commitWithSelectedAndStarred
849+
)
850+
851+
commitsBySha[commit.sha as string] = [
852+
commitWithSelectedAndStarred,
853+
...(experiments || [])
854+
].filter(exp => !!filterExperiment(filters, exp))
855+
}
856+
857+
return commitsBySha
858+
}
859+
860+
private getFlattenedRowData(workspaceRow: Commit): Commit[] {
861+
const commitsBySha: { [sha: string]: Commit[] } =
862+
this.applyFiltersToFlattenedCommits()
863+
const rows = []
864+
865+
for (const { branch, sha } of this.rowOrder) {
866+
const commitsAndExps = commitsBySha[sha]
867+
if (!commitsAndExps) {
868+
continue
869+
}
870+
871+
rows.push(
872+
...commitsAndExps.map(commitOrExp => ({ ...commitOrExp, branch }))
873+
)
874+
}
875+
876+
return [workspaceRow, ...sortExperiments(this.getSorts(), rows)]
877+
}
832878
}

extension/src/test/fixtures/expShow/base/columns.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const nestedParamsFile = join('nested', 'params.yaml')
1010

1111
export const dataColumnOrder: string[] = [
1212
'id',
13+
'branch',
14+
'commit',
1315
'Created',
1416
'metrics:summary.json:accuracy',
1517
'metrics:summary.json:loss',
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
import { join } from 'path'
2+
import { Column, ColumnType } from '../../../../experiments/webview/contract'
3+
import { buildMetricOrParamPath } from '../../../../experiments/columns/paths'
4+
import { timestampColumn } from '../../../../experiments/columns/constants'
5+
6+
const nestedParamsFile = join('nested', 'params.yaml')
7+
8+
const data: Column[] = [
9+
timestampColumn,
10+
{
11+
type: ColumnType.METRICS,
12+
hasChildren: true,
13+
label: 'summary.json',
14+
parentPath: buildMetricOrParamPath(ColumnType.METRICS),
15+
path: buildMetricOrParamPath(ColumnType.METRICS, 'summary.json')
16+
},
17+
{
18+
type: ColumnType.METRICS,
19+
hasChildren: false,
20+
label: 'loss',
21+
parentPath: buildMetricOrParamPath(ColumnType.METRICS, 'summary.json'),
22+
path: buildMetricOrParamPath(ColumnType.METRICS, 'summary.json', 'loss'),
23+
pathArray: [ColumnType.METRICS, 'summary.json', 'loss'],
24+
firstValueType: 'number'
25+
},
26+
{
27+
type: ColumnType.METRICS,
28+
hasChildren: false,
29+
label: 'accuracy',
30+
parentPath: buildMetricOrParamPath(ColumnType.METRICS, 'summary.json'),
31+
path: buildMetricOrParamPath(
32+
ColumnType.METRICS,
33+
'summary.json',
34+
'accuracy'
35+
),
36+
pathArray: [ColumnType.METRICS, 'summary.json', 'accuracy'],
37+
firstValueType: 'number'
38+
},
39+
{
40+
type: ColumnType.METRICS,
41+
hasChildren: false,
42+
label: 'val_loss',
43+
parentPath: buildMetricOrParamPath(ColumnType.METRICS, 'summary.json'),
44+
path: buildMetricOrParamPath(
45+
ColumnType.METRICS,
46+
'summary.json',
47+
'val_loss'
48+
),
49+
pathArray: [ColumnType.METRICS, 'summary.json', 'val_loss'],
50+
firstValueType: 'number'
51+
},
52+
{
53+
type: ColumnType.METRICS,
54+
hasChildren: false,
55+
label: 'val_accuracy',
56+
parentPath: buildMetricOrParamPath(ColumnType.METRICS, 'summary.json'),
57+
path: buildMetricOrParamPath(
58+
ColumnType.METRICS,
59+
'summary.json',
60+
'val_accuracy'
61+
),
62+
pathArray: [ColumnType.METRICS, 'summary.json', 'val_accuracy'],
63+
firstValueType: 'number'
64+
},
65+
{
66+
type: ColumnType.PARAMS,
67+
hasChildren: true,
68+
label: 'params.yaml',
69+
parentPath: ColumnType.PARAMS,
70+
path: buildMetricOrParamPath(ColumnType.PARAMS, 'params.yaml')
71+
},
72+
{
73+
type: ColumnType.PARAMS,
74+
hasChildren: false,
75+
label: 'code_names',
76+
parentPath: buildMetricOrParamPath(ColumnType.PARAMS, 'params.yaml'),
77+
path: buildMetricOrParamPath(
78+
ColumnType.PARAMS,
79+
'params.yaml',
80+
'code_names'
81+
),
82+
pathArray: [ColumnType.PARAMS, 'params.yaml', 'code_names'],
83+
firstValueType: 'array'
84+
},
85+
{
86+
type: ColumnType.PARAMS,
87+
hasChildren: false,
88+
label: 'epochs',
89+
parentPath: buildMetricOrParamPath(ColumnType.PARAMS, 'params.yaml'),
90+
path: buildMetricOrParamPath(ColumnType.PARAMS, 'params.yaml', 'epochs'),
91+
pathArray: [ColumnType.PARAMS, 'params.yaml', 'epochs'],
92+
firstValueType: 'number'
93+
},
94+
{
95+
type: ColumnType.PARAMS,
96+
hasChildren: false,
97+
label: 'learning_rate',
98+
parentPath: buildMetricOrParamPath(ColumnType.PARAMS, 'params.yaml'),
99+
path: buildMetricOrParamPath(
100+
ColumnType.PARAMS,
101+
'params.yaml',
102+
'learning_rate'
103+
),
104+
pathArray: [ColumnType.PARAMS, 'params.yaml', 'learning_rate'],
105+
firstValueType: 'number'
106+
},
107+
{
108+
type: ColumnType.PARAMS,
109+
hasChildren: false,
110+
label: 'dvc_logs_dir',
111+
parentPath: buildMetricOrParamPath(ColumnType.PARAMS, 'params.yaml'),
112+
path: buildMetricOrParamPath(
113+
ColumnType.PARAMS,
114+
'params.yaml',
115+
'dvc_logs_dir'
116+
),
117+
pathArray: [ColumnType.PARAMS, 'params.yaml', 'dvc_logs_dir'],
118+
firstValueType: 'string'
119+
},
120+
{
121+
type: ColumnType.PARAMS,
122+
hasChildren: false,
123+
label: 'log_file',
124+
parentPath: buildMetricOrParamPath(ColumnType.PARAMS, 'params.yaml'),
125+
path: buildMetricOrParamPath(ColumnType.PARAMS, 'params.yaml', 'log_file'),
126+
pathArray: [ColumnType.PARAMS, 'params.yaml', 'log_file'],
127+
firstValueType: 'string'
128+
},
129+
{
130+
type: ColumnType.PARAMS,
131+
hasChildren: false,
132+
label: 'dropout',
133+
parentPath: buildMetricOrParamPath(ColumnType.PARAMS, 'params.yaml'),
134+
path: buildMetricOrParamPath(ColumnType.PARAMS, 'params.yaml', 'dropout'),
135+
pathArray: [ColumnType.PARAMS, 'params.yaml', 'dropout'],
136+
firstValueType: 'number'
137+
},
138+
{
139+
type: ColumnType.PARAMS,
140+
hasChildren: true,
141+
label: 'process',
142+
parentPath: buildMetricOrParamPath(ColumnType.PARAMS, 'params.yaml'),
143+
path: buildMetricOrParamPath(ColumnType.PARAMS, 'params.yaml', 'process')
144+
},
145+
{
146+
type: ColumnType.PARAMS,
147+
hasChildren: false,
148+
label: 'threshold',
149+
parentPath: buildMetricOrParamPath(
150+
ColumnType.PARAMS,
151+
'params.yaml',
152+
'process'
153+
),
154+
path: buildMetricOrParamPath(
155+
ColumnType.PARAMS,
156+
'params.yaml',
157+
'process',
158+
'threshold'
159+
),
160+
pathArray: [ColumnType.PARAMS, 'params.yaml', 'process', 'threshold'],
161+
firstValueType: 'number'
162+
},
163+
{
164+
type: ColumnType.PARAMS,
165+
hasChildren: true,
166+
label: nestedParamsFile,
167+
parentPath: ColumnType.PARAMS,
168+
path: buildMetricOrParamPath(ColumnType.PARAMS, nestedParamsFile)
169+
},
170+
{
171+
type: ColumnType.PARAMS,
172+
hasChildren: false,
173+
label: 'test',
174+
parentPath: buildMetricOrParamPath(ColumnType.PARAMS, nestedParamsFile),
175+
path: buildMetricOrParamPath(ColumnType.PARAMS, nestedParamsFile, 'test'),
176+
pathArray: [ColumnType.PARAMS, nestedParamsFile, 'test'],
177+
firstValueType: 'boolean'
178+
},
179+
{
180+
type: ColumnType.PARAMS,
181+
hasChildren: false,
182+
label: 'test_arg',
183+
parentPath: buildMetricOrParamPath(
184+
ColumnType.PARAMS,
185+
'params.yaml',
186+
'process'
187+
),
188+
path: buildMetricOrParamPath(
189+
ColumnType.PARAMS,
190+
'params.yaml',
191+
'process',
192+
'test_arg'
193+
),
194+
pathArray: [ColumnType.PARAMS, 'params.yaml', 'process', 'test_arg'],
195+
firstValueType: 'string'
196+
}
197+
]
198+
199+
export default data

0 commit comments

Comments
 (0)