Skip to content

Commit

Permalink
Add support for showing inputs/outputs for selected layer node
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 696388822
  • Loading branch information
Google AI Edge authored and copybara-github committed Nov 14, 2024
1 parent 7e16ef3 commit ab7f7a2
Show file tree
Hide file tree
Showing 8 changed files with 947 additions and 618 deletions.
4 changes: 4 additions & 0 deletions src/ui/src/components/home_page/home_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
SETTING_EDGE_COLOR,
SETTING_EDGE_LABEL_FONT_SIZE,
SETTING_HIDE_OP_NODES_WITH_LABELS,
SETTING_HIGHLIGHT_LAYER_NODE_INPUTS_OUTPUTS,
SETTING_KEEP_LAYERS_WITH_A_SINGLE_CHILD,
SETTING_MAX_CONST_ELEMENT_COUNT_LIMIT,
SETTING_SHOW_OP_NODE_OUT_OF_LAYER_EDGES_WITHOUT_SELECTING,
Expand Down Expand Up @@ -351,6 +352,9 @@ export class HomePage implements AfterViewInit {
this.settingsService.getBooleanValue(
SETTING_SHOW_OP_NODE_OUT_OF_LAYER_EDGES_WITHOUT_SELECTING,
),
highlightLayerNodeInputsOutputs: this.settingsService.getBooleanValue(
SETTING_HIGHLIGHT_LAYER_NODE_INPUTS_OUTPUTS,
),
};
}

Expand Down
3 changes: 3 additions & 0 deletions src/ui/src/components/visualizer/common/visualizer_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ export declare interface VisualizerConfig {
*/
showOpNodeOutOfLayerEdgesWithoutSelecting?: boolean;

/** Whether to highlight layer node inputs and outputs. */
highlightLayerNodeInputsOutputs?: boolean;

/** The default node styler rules. */
nodeStylerRules?: NodeStylerRule[];

Expand Down
327 changes: 198 additions & 129 deletions src/ui/src/components/visualizer/info_panel.ng.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
</div>

<!-- Inputs -->
<div class="section inputs" *ngIf="flatInputItems.length > 0" #inputsSectionEle
<div class="section inputs" *ngIf="inputItems.length > 0" #inputsSectionEle
[class.collapsed]="isSectionCollapsed(SectionLabel.INPUTS)">
<div class="header input">
<div class="header-label-container">
Expand All @@ -78,64 +78,8 @@
</paginator>
}
</div>
<div class="flat-items-container">
@for (item of flatInputItems; track item.opNode.id; let i = $index) {
<div class="flat-item">
<div class="name-row"
[class.search-match]="isSearchMatchedInputValue(getInputTensorTag(item)) || isSearchMatchedInputValue(item.opNode.label)">
<div class="index">{{item.index}}</div>
@if (item.opNode.hideInLayout) {
<div class="name">{{getInputName(item)}}</div>
} @else {
<div class="name locator"
[attr.data-id]="item.opNode.id"
(click)="handleLocateNode(item.opNode.id, $event)">
{{getInputName(item)}}
<div class="locator-icon-container"
[matTooltip]="locatorTooltip"
matTooltipClass="multiline-tooltip-left"
matTooltipPosition="right">
<mat-icon class="locator-icon">my_location</mat-icon>
</div>
<div class="filler"></div>
@if (!item.opNode.hideInLayout) {
<div class="visibility-icon-container input"
[matTooltip]="getInputOpNodeToggleVisibilityTooltip(item.opNode.id)"
matTooltipPosition="left"
[class.visible]="getInputOpNodeToggleVisible(item.opNode.id)"
(click)="handleToggleInputOpNodeVisibility(item.opNode.id, flatInputItems, $event)">
<mat-icon>
{{getInputOpNodeToggleVisibilityIcon(item.opNode.id)}}
</mat-icon>
</div>
}
</div>
}
</div>
<table class="metadata-table">
@for (metadataItem of item.metadataList; track metadataItem.key) {
@if (getShowMetadata(metadataItem)) {
<tr #rowEle
[class.search-match]="isSearchMatchedInputValue(metadataItem.value)">
<td class="key">
<div class="key-container">
<mat-icon class="bullet">circle</mat-icon>
<hoverable-label [label]="metadataItem.key"></hoverable-label>
</div>
</td>
<td class="value">
<expandable-info-text
[text]="metadataItem.value"
[type]="metadataItem.key">
</expandable-info-text>
</td>
</tr>
}
}
</table>
</div>
}
</div>
<ng-container *ngTemplateOutlet="inputItemsTmpl;context:{'items': inputItemsForCurPage}">
</ng-container>
</div>

<!-- Outputs -->
Expand All @@ -155,75 +99,8 @@
</paginator>
}
</div>
<div class="flat-items-container">
@for (item of outputItemsForCurPage; track item.outputId; let i = $index; let last = $last) {
<div class="flat-item">
<div class="name-row"
[class.search-match]="isSearchMatchedOutputValue(item.tensorTag)">
<div class="index">{{item.index}}</div>
<div class="name">{{getOutputName(item)}}</div>
<div class="filler"></div>
@if (getHasConnectedToNodes(item)) {
<div class="visibility-icon-container output"
[class.visible]="getOutputToggleVisible(item.outputId)"
[matTooltip]="getOutputToggleVisibilityTooltip(item.outputId)"
matTooltipPosition="left"
(click)="handleToggleOutputVisibility(item.outputId, outputItemsForCurPage, $event)">
<mat-icon>
{{getOutputToggleVisibilityIcon(item.outputId)}}
</mat-icon>
</div>
}
</div>
@if (item.metadataList.length > 0) {
<table class="metadata-table">
@for (metadataItem of item.metadataList; track metadataItem.key) {
<tr [class.search-match]="isSearchMatchedOutputValue(metadataItem.value)">
<td class="key">
<div class="key-container">
<mat-icon class="bullet">circle</mat-icon>
<hoverable-label [label]="metadataItem.key"></hoverable-label>
</div>
</td>
<td class="value">
@if (metadataItem.key === outputMetadataConnectedTo) {
@for (targetNode of metadataItem.connectedNodes; track targetNode.id) {
<div class="target-node-container"
[attr.data-id]="targetNode.id"
[class.search-match]="isSearchMatchedOutputValue(targetNode.label)"
[bubble]="namespacePopup"
[overlaySize]="constValuesPopupSize"
[overlayPositions]="outputConnectsToNamespacePopupPosition"
[hoverDelayMs]="50"
(click)="handleLocateNode(targetNode.id, $event)">
{{targetNode.label}}
<div class="locator-icon-container"
[matTooltip]="locatorTooltip"
matTooltipClass="multiline-tooltip-left"
matTooltipPosition="right">
<mat-icon class="locator-icon">my_location</mat-icon>
</div>
</div>
<ng-template #namespacePopup>
<div class="model-explorer-const-values-popup">
<ng-container *ngTemplateOutlet="namespaceHierarchy;context:{'value': getNamespaceLabel(targetNode)}">
</ng-container>
</div>
</ng-template>
}
} @else {
<expandable-info-text
[text]="metadataItem.value">
</expandable-info-text>
}
</td>
</tr>
}
</table>
}
</div>
}
</div>
<ng-container *ngTemplateOutlet="outputItemsTmpl;context:{'items': outputItemsForCurPage}">
</ng-container>
</div>

<!-- Identical groups -->
Expand All @@ -246,6 +123,48 @@
<io-tree [data]="identicalGroupsData" [rendererId]="curRendererId">
</io-tree>
</div>

<!-- Group inputs -->
<div class="section inputs" *ngIf="groupInputItems.length > 0" #groupInputsSectionEle
[class.collapsed]="isSectionCollapsed(SectionLabel.GROUP_INPUTS)">
<div class="header input">
<div class="header-label-container">
<button mat-icon-button class="toggle"
(click)="handleToggleSection(SectionLabel.GROUP_INPUTS, groupInputsSectionEle)">
<mat-icon>{{getSectionToggleIcon(SectionLabel.GROUP_INPUTS)}}</mat-icon>
</button>
layer inputs ({{curGroupInputsCount}})
</div>
@if (showGroupInputPaginator) {
<paginator [pageSize]="ioPageSize" [itemsCount]="curGroupInputsCount"
(change)="handleGroupInputPaginatorChanged($event)">
</paginator>
}
</div>
<ng-container *ngTemplateOutlet="inputItemsTmpl;context:{'items': groupInputItemsForCurPage}">
</ng-container>
</div>

<!-- Group outputs -->
<div class="section outputs" *ngIf="groupOutputItems.length > 0" #groupOutputsSectionEle
[class.collapsed]="isSectionCollapsed(SectionLabel.GROUP_OUTPUTS)">
<div class="header output">
<div class="header-label-container">
<button mat-icon-button class="toggle"
(click)="handleToggleSection(SectionLabel.GROUP_OUTPUTS, groupOutputsSectionEle)">
<mat-icon>{{getSectionToggleIcon(SectionLabel.GROUP_OUTPUTS)}}</mat-icon>
</button>
layer outputs ({{curGroupOutputsCount}})
</div>
@if (showGroupOutputPaginator) {
<paginator [pageSize]="ioPageSize" [itemsCount]="curGroupOutputsCount"
(change)="handleGroupOutputPaginatorChanged($event)">
</paginator>
}
</div>
<ng-container *ngTemplateOutlet="outputItemsTmpl;context:{'items': groupOutputItemsForCurPage}">
</ng-container>
</div>
</div>

<!-- Resizer -->
Expand All @@ -270,4 +189,154 @@
</div>
}
</div>
</ng-template>
</ng-template>

<ng-template #inputItemsTmpl let-items="items">
<div class="flat-items-container">
@for (item of items; track item.opNode.id; let i = $index) {
<div class="flat-item">
<div class="name-row"
[class.search-match]="isSearchMatchedInputValue(getInputTensorTag(item)) || isSearchMatchedInputValue(item.opNode.label)">
<div class="index">{{item.index}}</div>
@if (item.opNode.hideInLayout) {
<div class="name">{{getInputName(item)}}</div>
@if (item.targetOpNode) {
<div class="target-op-container">
<mat-icon class="arrow">arrow_forward</mat-icon>
<div class="target-op-node-label">{{item.targetOpNode.label}}</div>
</div>
}
} @else {
<div class="name locator"
[attr.data-id]="item.opNode.id"
(click)="handleLocateNode(item.opNode.id, $event)">
{{getInputName(item)}}
<div class="locator-icon-container"
[matTooltip]="locatorTooltip"
matTooltipClass="multiline-tooltip-left"
matTooltipPosition="right">
<mat-icon class="locator-icon">my_location</mat-icon>
</div>
@if (item.targetOpNode) {
<div class="target-op-container">
<mat-icon class="arrow">arrow_forward</mat-icon>
<div class="target-op-node-label">{{item.targetOpNode.label}}</div>
</div>
}
<div class="filler"></div>
@if (!item.opNode.hideInLayout) {
<div class="visibility-icon-container input"
[matTooltip]="getInputOpNodeToggleVisibilityTooltip(item.opNode.id)"
matTooltipPosition="left"
[class.visible]="getInputOpNodeToggleVisible(item.opNode.id)"
(click)="handleToggleInputOpNodeVisibility(item.opNode.id, items, $event)">
<mat-icon>
{{getInputOpNodeToggleVisibilityIcon(item.opNode.id)}}
</mat-icon>
</div>
}
</div>
}
</div>
<table class="metadata-table">
@for (metadataItem of item.metadataList; track metadataItem.key) {
@if (getShowMetadata(metadataItem)) {
<tr #rowEle
[class.search-match]="isSearchMatchedInputValue(metadataItem.value)">
<td class="key">
<div class="key-container">
<mat-icon class="bullet">circle</mat-icon>
<hoverable-label [label]="metadataItem.key"></hoverable-label>
</div>
</td>
<td class="value">
<expandable-info-text
[text]="metadataItem.value"
[type]="metadataItem.key">
</expandable-info-text>
</td>
</tr>
}
}
</table>
</div>
}
</div>
</ng-template>

<ng-template #outputItemsTmpl let-items="items">
<div class="flat-items-container">
@for (item of items; track $index; let i = $index; let last = $last) {
<div class="flat-item">
<div class="name-row"
[class.search-match]="isSearchMatchedOutputValue(item.tensorTag)">
<div class="index">{{item.index}}</div>
<div class="name">{{getOutputName(item)}}</div>
@if (item.showSourceOpNode) {
<div class="source-op-node-label">
({{item.sourceOpNode.label}})
</div>
}
<div class="filler"></div>
@if (getHasConnectedToNodes(item)) {
<div class="visibility-icon-container output"
[class.visible]="getOutputToggleVisible(item)"
[matTooltip]="getOutputToggleVisibilityTooltip(item)"
matTooltipPosition="left"
(click)="handleToggleOutputVisibility(item, items, $event)">
<mat-icon>
{{getOutputToggleVisibilityIcon(item)}}
</mat-icon>
</div>
}
</div>
@if (item.metadataList.length > 0) {
<table class="metadata-table">
@for (metadataItem of item.metadataList; track metadataItem.key) {
<tr [class.search-match]="isSearchMatchedOutputValue(metadataItem.value)">
<td class="key">
<div class="key-container">
<mat-icon class="bullet">circle</mat-icon>
<hoverable-label [label]="metadataItem.key"></hoverable-label>
</div>
</td>
<td class="value">
@if (metadataItem.key === outputMetadataConnectedTo) {
@for (targetNode of metadataItem.connectedNodes; track targetNode.id) {
<div class="target-node-container"
[attr.data-id]="targetNode.id"
[class.search-match]="isSearchMatchedOutputValue(targetNode.label)"
[bubble]="namespacePopup"
[overlaySize]="constValuesPopupSize"
[overlayPositions]="outputConnectsToNamespacePopupPosition"
[hoverDelayMs]="50"
(click)="handleLocateNode(targetNode.id, $event)">
{{targetNode.label}}
<div class="locator-icon-container"
[matTooltip]="locatorTooltip"
matTooltipClass="multiline-tooltip-left"
matTooltipPosition="right">
<mat-icon class="locator-icon">my_location</mat-icon>
</div>
</div>
<ng-template #namespacePopup>
<div class="model-explorer-const-values-popup">
<ng-container *ngTemplateOutlet="namespaceHierarchy;context:{'value': getNamespaceLabel(targetNode)}">
</ng-container>
</div>
</ng-template>
}
} @else {
<expandable-info-text
[text]="metadataItem.value">
</expandable-info-text>
}
</td>
</tr>
}
</table>
}
</div>
}
</div>
</ng-template>
Loading

0 comments on commit ab7f7a2

Please sign in to comment.